'======================================
' Parametric Flammulate/Reticulate pattern generator
'======================================
' Cesare Brizio, 20 October 2022
'
' Version 5.82 Retrograde
Version="5.82 Retrograde"
'
' Version 5.82: resolved conflict between chevron visualization and reticulation visualization
' Version 5.81: Added new option to eliminate initial delay of Generators at half-step in supervised renderings (all the generators will fire immediately)
' Version 5.8: Added new user interface with buttons
' Version 5.7: Added up to 4 generation cycles (with slight offset to the right), four sizes of "circle of inhibition", option for chevron/reticulation survival after fire cycles expired
' Version 5.7: Redesigned collision control and front reset strategy
' Version 5.69: Paradigm revolution - No proactive control of state changes, Generators are assigned a last_cycle value
' when their state changes
' Version 5.69: Enabled Reticulation - with several residual problems
' Version 5.65: Enabled flammules without visible background
' Version 5.5 / 5.6: Improved collision detection, reset after collision, revised the collisions occurring when collision control
' is suspended, corrected a few errors in the inactivation of propagation fronts, added "orphan pixel"
' detection to fill residual gaps in contours after collision
' Version 5.0: Each «F» front is assigned an unique one-character ID, useful for selective inactivation when collision control
' is suspended
' Version 5.0: added optional inactive band, optional line on front inactivation, and collision control was made optional
' Version 4.0: one inactive state - "W" (Wait) - 1 Active States - "F" (Fire)
' Version 3.0: two inactive states - "C" (Charge), "W" (Wait) - 1 Active States - "F" (Fire)
' All three states have a Current Duration and an Expected Duration, randomized between minimum and maximum values
' Version 2.0: two inactive states - "C" (Charge), "W" (Wait) - 3 Active States - "F" (Fire), "U" (Up), "D" (Down)
' Charge and Wait have a Current Duration and an Expected Duration, randomized between minimum and maximum values
' NOTE: VERSION 2.0 was aborted as soon as it became apparent that "U" and "D" states were useless
' Version 1.0: one inactive state - "N" (No propagation) - 3 Active States - "B" (Both), "U" (Up), "D" (Down)
' State "N" has a Current Latency and an Expected Latency
'
' Partly inspired by:
' Bernard Tursch & Dietmar Greifeneder
' «Oliva Shells - The genus Oliva and the species problem»
' L'Informatore Piceno (Italy), 2001
'
' Hans Meinhardt
' «The Algirithmic Beauty of Seashells»
' Springer, 1995
'
'
'======================================
'======================
' Activate debug by setting
' the DEBUG variable to "True"
'======================
'DEBUG = "True"
DEBUG = "False"
'======================
'--------------------------------------------------------------------------------------------------------------------------------'
' Graphics Initialization:
'--------------------------------------------------------------------------------------------------------------------------------'
GeneralBackgroundColor="Wheat"
Flammule_LINE_Color="FireBrick"
GraphicsWindow.BackgroundColor = GeneralBackgroundColor
GraphicsWindow.BrushColor = "Black"
GraphicsWindow.CanResize="True"
GraphicsWindow.FontName="Roboto"
GraphicsWindow.FontSize = 14
GraphicsWindow.Height = 750
GraphicsWindow.Left= 0
GraphicsWindow.Title = "Flammulate Pattern Generator"
GraphicsWindow.Top = 0
GraphicsWindow.Width = 1200
BkgColor[1] = "White"
BkgColor[2] = "Seashell"
BkgColor[3] = "LightYellow"
BkgColor[4] = "Ivory"
BkgColor[5] = "White"
BkgColor[6] = "Seashell"
BkgColor[7] = "LightYellow"
BkgColor[8] = "Ivory"
BkgColor[9] = "White"
BkgColor[10] = "Seashell"
'--------------------------------------------------------------------------------------------------------------------------------'
' Assign one-character identification code to each one of the 500 Generators
'--------------------------------------------------------------------------------------------------------------------------------'
Assign_Gen_Code()
'--------------------------------------------------------------------------------------------------------------------------------'
' Load Sample Images:
'--------------------------------------------------------------------------------------------------------------------------------'
Load_Image_Samples()
'--------------------------------------------------------------------------------------------------------------------------------'
' Controls Initialization:
'--------------------------------------------------------------------------------------------------------------------------------'
InitControls()
Controls.ButtonClicked = OnButtonClick
'--------------------------------------------------------------------------------------------------------------------------------'
' Messages Initialization:
'--------------------------------------------------------------------------------------------------------------------------------'
CRLF = Text.GetCharacter(13) + Text.GetCharacter(10)
InitMessages()
'--------------------------------------------------------------------------------------------------------------------------------'
' Show Opening message:
'--------------------------------------------------------------------------------------------------------------------------------'
Curr_Text = Opening
GraphicsWindow.ShowMessage(Curr_Text,"Oliva Shell Pattern Generator 5.82r")
'--------------------------------------------------------------------------------------------------------------------------------'
' Graphic Windows Caption Initialization:
'--------------------------------------------------------------------------------------------------------------------------------'
Graph_Win_Caps()
'--------------------------------------------------------------------------------------------------------------------------------'
' Parameters Initialization:
'--------------------------------------------------------------------------------------------------------------------------------'
Parameters_Initialize()
'--------------------------------------------------------------------------------------------------------------------------------'
' Button Wait Loop:
'--------------------------------------------------------------------------------------------------------------------------------'
Loop:
If Button <> "" Then ' Waits until Button is retrieved from Sub OnButtonClick.
CheckButtons()
Button = ""
ButtonCap = ""
EndIf
Program.Delay(100) ' A quick delay to avoid heating up CPU!
Goto Loop
'====================================================================================================
'====================================================================================================
'====================================================================================================
'====================================================================================================
' SUBROUTINES
'====================================================================================================
'====================================================================================================
'====================================================================================================
'====================================================================================================
' Subroutines are listed in alphabetical order by subroutine name
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' ACTIVATE(GENERATE) - Change state from «W» to «F» for the generator «WhichGen». Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' ASK PARAMETERS - OPEN A TEXT WINDOW AND ASK PARAMETERS, THEN ACTIVATE «GENERATE» BUTTON. Invoked on button click.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' ASSIGN_GEN_CODE(GENERATE) - Assigns a semi-unique one-character identifier to each generator, to mark propagation fronts. Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' CHECKBUTTONS - CHECK WHICH BUTTON WAS CLICKED AND TAKE SPECIFIC ACTIONS. Invoked on button click.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' CHOOSE_PRESET - LOAD ONE OF THE FIVE PRESETS, THEN ACTIVATE «GENERATE» BUTTON. Invoked by five similar buttons.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' CLEAR_AND_HIDE_CONTROLS - CLEAR GRAPHICS WINDOW AND HIDE CONTROLS. Invoked before loading an image example or before new rendering.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' GENERATE - EXECUTES THE REQUIRED RENDERING. Invoked on button click.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' GRAPH_WIN_CAPS - INITIALIZE GRAPHICS WINDOW CAPTIONS. Invoked whenever a graphics window reset occurs.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' INITCONTROLS - INITIALIZE CONTROLS ( CREATE BUTTONS ). Invoked by main program.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' INITMESSAGES - INITIALIZE EXPLANATORY TEXTS. Invoked by main program.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' LOAD_IMAGE_SAMPLES - LOAD FIVE SAMPLE IMAGES. Invoked by main program.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' MANAGE_RETICULATION(GENERATE) - Manages the propagation of flammule borders, separately from the front propagation. Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' MESSAGE_0_0_AND_WAIT(GENERATE) - Displays a Text Window Message in location 0,0. It may wait for ENTER or not, depending on parameters. Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' NOTHING(GENERATE) - Does nothing. An expedient to keep open alternative instructions. Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' ONBUTTONCLICK - RETURNS THE CAPTION OF ANY BUTTON CLICKED. Assigned by main program.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' PARAMETERS_INITIALIZE - INITIALIZE AND DISPLAY EMPTY PARAMETERS. Invoked whenever a graphics window reset occurs.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' PROPAGATE_F_STATE(GENERATE) - Propagate the «F» state to adjacent Generators. Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' RANDOMIZE_LAST_WAIT_CYCLE(GENERATE) - Randomizes required fire cycles for the generator «WhichGen». Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' RESET_AND_SHOW_CONTROLS - RESET GRAPHICS WINDOW AND SHOW CONTROLS. Invoked after loading an image example or after rendering.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' RESET_NEXT_GEN_STATE(GENERATE) - Resets NEXT GENERATOR STATE for the generator «WhichGen». Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' RESET_CURR_GEN_STATE(GENERATE) - Resets CURRENT GENERATOR STATE for the generator «WhichGen». Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' SET_REQUIRED_FIRE_CYCLES(GENERATE) - Sets required FIRE cycles for the generator «WhichGen». Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' SET_REQUIRED_WAIT_CYCLES(GENERATE) - Sets required wait cycles for the generator «WhichGen». Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' SHOW_EXAMPLE - SHOW THE SELECTED IMAGE SAMPLE. Invoked by five similar buttons.
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' UPDATE_DEBUG_LINE(GENERATE) - Updates a debug line in the text window, displaying a "character mode" view of the rendering. Invoked by GENERATE().
'----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'=========================
'=========================
' ACTIVATE
'=========================
'=========================
Sub Activate
' *===> HERE WHEN User has chosen unrestrained activation
' *===> OR WHEN User has chosen supervised (non randomic) activation
' *===> and this generator was selected as active
' *===> AND WHEN WAIT cycles are expired
' *===> AND WHEN no adjacent generators are in state «F»
' *===> AND WHEN the generator is not the upmost or the bottommos
'Put the Generator in state «F»
next_prop_stat[WhichGen] = "F" ' FIRE (two lines will diverge)
'=========================================================
'===========> The "generator code" of the generator that promoted this «F»
'===========> will mark all the «activation Wave» / propagation front
'=========================================================
ActCode[WhichGen] = GenCode[WhichGen]
'=========================================================
'===========> The chevron lines propagation used in the "reticulation control"
'===========> are initialized for propagation
'=========================================================
NextBorderState[WhichGen] = "B"
'=========================================================
'===========> The last activation of the current generator occurred at the
'===========> current OP_ITERATION. This may help understanding which
'===========> activation front is younger
'=========================================================
Cycle_Activated[WhichGen] = OP_ITERATION
'=========================================================
'===========> The last fire cycle will occur Required_Fire_Cycles
'===========> after the current OP_ITERATION.
'=========================================================
Last_Fire_Cycle[WhichGen] = OP_ITERATION + Required_Fire_Cycles[WhichGen]
'=========================================================
'===========> Monitor_Fire_Expired is the number of the Generator that
'===========> initiated a propagation front. All the Generators in the front
'===========> will monitor the expiration of fire cycles of their initial promoter.
Monitor_Fire_Expired[WhichGen] = WhichGen
'------------------------> DEBUG starts
If DEBUG Then '-> DEBUG
Waitkey="True" '-> DEBUG
Message_00="Line 1993 - Just activated new F generator with - ActCode ["+WhichGen+"] = >"+ActCode[WhichGen]+"< from GenCode "+GenCode[WhichGen] '-> DEBUG
MESSAGE_0_0_AND_WAIT() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG ends
EndSub
'=====================================================
'=====================================================
' OPEN A TEXT WINDOW AND ASK PARAMETERS
'=====================================================
'=====================================================
Sub Ask_Parameters
TextWindow.Top = 200
TextWindow.Left = 600
TextWindow.Clear()
TextWindow.Show()
TextWindow.ForegroundColor = "Yellow"
line_above = "╔"
For c = 1 To 78
line_above = line_above + "═"
EndFor
line_above = line_above + "╗"
line_below = "╚"
For c = 1 To 78
line_below = line_below + "═"
EndFor
line_below = line_below + "╝"
TextWindow.ForegroundColor = "White"
TextWindow.WriteLine(line_above)
TextWindow.WriteLine("║ ║")
TextWindow.WriteLine("║ "+"BUTTONS IN THE GRAPHICS WINDOW PROVIDE INFORMATION ABOUT EACH PARAMETER"+" ║")
TextWindow.WriteLine("║ "+"Please consult the explanations before activating manual input"+" ║")
TextWindow.WriteLine("║ ║")
TextWindow.WriteLine("║ "+"IF IN DOUBT, BY CLOSING THIS TEXT WINDOW YOU WILL STOP THE APPLICATION"+" ║")
TextWindow.WriteLine("║ ║")
TextWindow.WriteLine(line_below)
TextWindow.WriteLine("")
'========================================
' MINIMUM NUMBER OF WAIT CYCLES
'========================================
TextWindow.WriteLine("Please Enter below the MINIMUM NUMBER OF WAIT CYCLES")
TextWindow.ForegroundColor = "Red"
TextWindow.WriteLine("Note: in Supervised generation, only the minimum value will be considered!")
TextWindow.ForegroundColor = "Yellow"
TextWindow.WriteLine("(Minimum value 4, maximum value 100, suggested range 1 - 100, e.g. 25):")
ASK_MIN_WAIT_AGAIN:
Min_Wait_Cycles = TextWindow.ReadNumber()
If Min_Wait_Cycles < 1 Or Min_Wait_Cycles > 100 Then
TextWindow.WriteLine("The MINIMUM NUMBER OF WAIT CYCLES must be between 4 and 100!")
Goto ASK_MIN_WAIT_AGAIN
EndIf
TextWindow.WriteLine("")
'================================
' MAXIMUM NUMBER OF WAIT CYCLES
'================================
TextWindow.WriteLine("Please Enter below the MAXIMUM NUMBER OF WAIT CYCLES")
TextWindow.ForegroundColor = "Red"
TextWindow.WriteLine("Note: in Supervised generation, only the minimum value will be considered!")
TextWindow.ForegroundColor = "Yellow"
TextWindow.WriteLine("(Minimum value "+Min_Wait_Cycles+", maximum value 150, suggested range 15 - 50, e.g. 40):")
ASK_MAX_WAIT_AGAIN:
Max_Wait_Cycles = TextWindow.ReadNumber()
If Max_Wait_Cycles < Min_Wait_Cycles Or Max_Wait_Cycles > 150 Then
TextWindow.WriteLine("The MAXIMUM NUMBER OF WAIT CYCLES must be between the MINIMUM NUMBER OF WAIT CYCLES and 150!")
Goto ASK_MAX_WAIT_AGAIN
EndIf
TextWindow.WriteLine("")
'========================================
' MINIMUM NUMBER OF FIRE CYCLES
'========================================
TextWindow.WriteLine("In absence of collisions between wavefronts, the number of FIRE CYCLES determines the maximum length of a chevron.")
TextWindow.WriteLine("Please Enter below the MINIMUM NUMBER OF FIRE CYCLES")
TextWindow.ForegroundColor = "Red"
TextWindow.WriteLine("Note: in Supervised generation, only the minimum value will be considered!")
TextWindow.ForegroundColor = "Yellow"
TextWindow.WriteLine("(Minimum value 4, maximum value 100, suggested range 8 - 40, e.g. 25):")
ASK_MIN_FIRE_AGAIN:
Min_Fire_Cycles = TextWindow.ReadNumber()
If Min_Fire_Cycles < 4 Or Min_Fire_Cycles > 100 Then
TextWindow.WriteLine("The MINIMUM NUMBER OF FIRE CYCLES must be between 4 and 100!")
Goto ASK_MIN_FIRE_AGAIN
EndIf
TextWindow.WriteLine("")
'================================
' MAXIMUM NUMBER OF FIRE CYCLES
'================================
TextWindow.WriteLine("Please Enter below the MAXIMUM NUMBER OF FIRE CYCLES")
TextWindow.ForegroundColor = "Red"
TextWindow.WriteLine("Note: in Supervised generation, only the minimum value will be considered!")
TextWindow.ForegroundColor = "Yellow"
TextWindow.WriteLine("(Minimum value "+Min_Fire_Cycles+", maximum value 150, suggested range 15 - 50, e.g. 40):")
ASK_MAX_FIRE_AGAIN:
Max_Fire_Cycles = TextWindow.ReadNumber()
If Max_Fire_Cycles < Min_Fire_Cycles Or Max_Fire_Cycles > 150 Then
TextWindow.WriteLine("The MAXIMUM NUMBER OF FIRE CYCLES must be between the MINIMUM NUMBER OF FIRE CYCLES and 150!")
Goto ASK_MAX_FIRE_AGAIN
EndIf
TextWindow.WriteLine("")
'=========================================
' STEP BETWEEN ACTIVE GENERATORS
'=========================================
TextWindow.WriteLine("To enable the generation of a realistic pattern, active Generators need to be spaced along the array:")
TextWindow.WriteLine("the lower the step, the finer the pattern that will be generated (depending also on wait cycles).")
ASK_STEP_AGAIN:
TextWindow.WriteLine("Please Enter below the step size in pixels:")
TextWindow.WriteLine("(Minimum value 10, maximum value 350, suggested range 30 - 90):")
Step_Size_Px = TextWindow.ReadNumber()
If Step_Size_Px < 10 Or Step_Size_Px > 350 Then
Goto ASK_STEP_AGAIN
EndIf
TextWindow.WriteLine("")
'=========================================
' SUPERVISED OR RANDOM INITIALIZATION?
'=========================================
TextWindow.WriteLine("Would you like a fully supervised simulation (E) or a random initialization (R)?")
ASK_EVEN_AGAIN:
TextWindow.WriteLine("Please enter «E» for an even preset or «R» for a random preset:")
Evenness = Text.ConvertToUpperCase(TextWindow.Read())
If Evenness<>"E" And Evenness<>"R" Then
TextWindow.WriteLine("You should enter «E» or «R»!")
Goto ASK_EVEN_AGAIN
EndIf
If Evenness = "R" Then
TextWindow.Write("Step will randomly vary between " + Math.Round(Step_Size_Px*0.85))
TextWindow.WriteLine(" and "+Math.Round(Step_Size_Px*1.15))
TextWindow.WriteLine("")
Else
TextWindow.WriteLine("Desired step size of "+Step_Size_Px+" may set ON up to")
TextWindow.WriteLine(Math.Round(500/Step_Size_Px)+" «F» Generators in the array.")
EndIf
TextWindow.WriteLine("")
'=========================================
' HALFSTEP DELAY/WAIT/OFFSET
'=========================================
If Evenness = "E" Then
TextWindow.WriteLine("In supervised (even) renderings, half of the generators are immediately ")
TextWindow.WriteLine("active and, at each half-step, a generator in state «W» is placed, so that")
TextWindow.WriteLine("a more interesting pattern is generated. User can opt for an immediate")
TextWindow.WriteLine("activation of all the generators, that will all start simultaneously.")
TextWindow.WriteLine("Would you like to adopt halfstep delay?")
ASK_HALFSTWAIT_AGAIN:
TextWindow.WriteLine("Please enter «Y» or «N»:")
HALFSTEP_DELAY = Text.ConvertToUpperCase(TextWindow.Read())
If HALFSTEP_DELAY<>"Y" And HALFSTEP_DELAY<>"N" Then
TextWindow.WriteLine("You should enter «Y» or «N»!")
Goto ASK_HALFSTWAIT_AGAIN
EndIf
Else
'=======> USELESS IN RANDOM RENDERINGS
'=======> Conventionally set to "N"
HALFSTEP_DELAY = "N"
EndIf
TextWindow.WriteLine("")
'=========================================
' RANGE OF INHIBITION
'=========================================
If Evenness = "R" Then
TextWindow.WriteLine("Spontaneous activation cannot occur in the immediate vicinities of a propagating generator.")
TextWindow.WriteLine("User can inhibit 2, 4, 8 or 16 positions away from the current generator.")
TextWindow.WriteLine("Ranges higher than 2 will progressively obliterate the smallest flammules.")
ASK_RINHIB_AGAIN:
TextWindow.WriteLine("Please enter the «range of inhibition» (2, 4, 8 or 16) :")
RANGE_INHIB = TextWindow.Read()
If RANGE_INHIB <> 2 And RANGE_INHIB <> 4 And RANGE_INHIB <> 8 And RANGE_INHIB <> 16 Then
TextWindow.WriteLine("You entered a value different from 2, 4, 8 or 16!")
Goto ASK_RINHIB_AGAIN
EndIf
Else
'=======> USELESS IN SUPERVISED RENDERINGS
'=======> Conventionally set to 2
RANGE_INHIB = 2
EndIf
TextWindow.WriteLine("")
'=========================================
' Should flammules be terminated by a line?
'=========================================
TextWindow.WriteLine("Would you like that, whenever propagation is interrupted, a line marks the inactivated front?")
ASK_TERMLINE_AGAIN:
TextWindow.WriteLine("Please enter «Y» for full perimetre or «N» for sides only:")
Mark_Inact_Front = Text.ConvertToUpperCase(TextWindow.Read())
If Mark_Inact_Front<>"Y" And Mark_Inact_Front<>"N" Then
TextWindow.WriteLine("You should enter «Y» or «N»!")
Goto ASK_TERMLINE_AGAIN
EndIf
TextWindow.WriteLine("")
'=========================================
' FLAMMULES BACKGROUND
'=========================================
TextWindow.WriteLine("Would you like the flammules to be filled (Y) or (N)?")
ASK_FILLFLAM_AGAIN:
TextWindow.WriteLine("Please enter «Y» or «N»:")
FillFlam = Text.ConvertToUpperCase(TextWindow.Read())
If FillFlam<>"Y" And FillFlam<>"N" Then
TextWindow.WriteLine("You should enter «Y» or «N»!")
Goto ASK_FILLFLAM_AGAIN
EndIf
TextWindow.WriteLine("")
'=========================================
' Should collisions stop flammule generation?
'=========================================
TextWindow.WriteLine("Would you like to maintain (Y) or suspend (N) collision check?")
ASK_NOCOLL_AGAIN:
TextWindow.WriteLine("Please enter «Y» or «N»:")
Collision_Check = Text.ConvertToUpperCase(TextWindow.Read())
If Collision_Check<>"Y" And Collision_Check<>"N" Then
TextWindow.WriteLine("You should enter «Y» or «N»!")
Goto ASK_NOCOLL_AGAIN
EndIf
TextWindow.WriteLine("")
'=========================================
' If collision control OFF, allow reticulation?
'=========================================
If Collision_Check = "N" Then
TextWindow.WriteLine("Would you like to allow (Y) or disable (N) reticulation?")
ASK_RETIC_AGAIN:
TextWindow.WriteLine("Please enter «Y» or «N»:")
Reticulation = Text.ConvertToUpperCase(TextWindow.Read())
If Reticulation<>"Y" And Reticulation<>"N" Then
TextWindow.WriteLine("You should enter «Y» or «N»!")
Goto ASK_RETIC_AGAIN
EndIf
Else
'if Collision_Check = "Y" , reticulation = "N"
Reticulation = "N"
EndIf
TextWindow.WriteLine("")
'=======================================================================
' If collision control OFF, and Reticulation enabled, should chevrons survive the end of fire cycles?
'=======================================================================
If Reticulation = "Y" Then
TextWindow.WriteLine("Would you like to allow (Y) or inhibit (N) chevron survival after collision?")
TextWindow.WriteLine("Note: if FILL FLAMMULES is «N», the reticulation in the flammule area will be overwritten")
TextWindow.WriteLine(" with background color, and only the chevrons from the spontaneously inactivating ")
TextWindow.WriteLine(" generators will survive.")
ASK_CHEV_SURV_FRONT_AGAIN:
TextWindow.WriteLine("Please enter «Y» or «N»:")
ChevSurv = Text.ConvertToUpperCase(TextWindow.Read())
If ChevSurv<>"Y" And ChevSurv<>"N" Then
TextWindow.WriteLine("You should enter «Y» or «N»!")
Goto ASK_CHEV_SURV_FRONT_AGAIN
EndIf
Else
'if Reticulation = "N", ChevSurv = "N"
ChevSurv = "N"
EndIf
TextWindow.WriteLine("")
'=========================================
' UNRESPONSIVE BAND
'=========================================
TextWindow.WriteLine("Would you like to include an UNRESPONSIVE BAND at the center of the rendering?")
ASK_UNRB_AGAIN:
TextWindow.WriteLine("Please enter 0 for no band or a value up to 100 for the number of generators")
TextWindow.WriteLine("in the unresponsive band:")
Unresponsive_Band = TextWindow.Read()
If Unresponsive_Band < 0 or Unresponsive_Band > 100 Then
TextWindow.WriteLine("You entered a value lower than 0 or higher than 100!")
Goto ASK_UNRB_AGAIN
EndIf
TextWindow.WriteLine("")
'=========================================
' NUMBER OF PASSES
'=========================================
TextWindow.WriteLine("Would you like to execute more than one (up to ten) full image generation cycles?")
ASK_PASSES_AGAIN:
TextWindow.WriteLine("Please enter the number of renderings that will be generated ( 1 to 10 ):")
MAX_PASSES = TextWindow.Read()
If MAX_PASSES < 1 or MAX_PASSES > 10 Then
TextWindow.WriteLine("You entered a value lower than 1 or higher than 10!")
Goto ASK_PASSES_AGAIN
EndIf
'=========================================
' OFFSET BETWEEN RENDERINGS
'=========================================
If MAX_PASSES > 1 Then
TextWindow.WriteLine("How many pixels should each new rendering be offset?")
ASK_OFFSET_AGAIN:
TextWindow.WriteLine("Please enter the offset in pixel ( 10 to 100 ):")
OFFSET = TextWindow.Read()
If OFFSET < 10 or OFFSET > 100 Then
TextWindow.WriteLine("You entered a value lower than 10 or higher than 100!")
Goto ASK_OFFSET_AGAIN
EndIf
EndIf
TextWindow.Hide()
'===================> Graphics Window is not self-clearing
'===================> new values will be overwritten above
'===================> existing values, unless cleared
GraphicsWindow.BrushColor=GraphicsWindow.BackgroundColor
GraphicsWindow.FillRectangle(538,170, 25, 500)
GraphicsWindow.BrushColor="Green"
GraphicsWindow.FontSize = 16
GraphicsWindow.DrawText(540,175, Min_Wait_Cycles)
GraphicsWindow.DrawText(540,201, Max_Wait_Cycles)
GraphicsWindow.DrawText(540,230, Min_Fire_Cycles)
GraphicsWindow.DrawText(540,256, Max_Fire_Cycles)
GraphicsWindow.DrawText(540,290, Step_Size_Px)
GraphicsWindow.DrawText(540,330, Evenness)
GraphicsWindow.DrawText(555,330, HALFSTEP_DELAY)
GraphicsWindow.DrawText(540,370, Mark_Inact_Front)
GraphicsWindow.DrawText(540,410, FillFlam)
GraphicsWindow.DrawText(540,450, Collision_Check)
GraphicsWindow.DrawText(540,490, Reticulation)
GraphicsWindow.DrawText(540,530, Unresponsive_Band)
GraphicsWindow.DrawText(540,570, RANGE_INHIB)
GraphicsWindow.DrawText(540,610, ChevSurv)
GraphicsWindow.DrawText(540,650, MAX_PASSES)
GraphicsWindow.DrawText(540,650, OFFSET)
Controls.ShowControl(GENRT)
EndSub
'=========================
'=========================
' ASSIGN GEN CODE
'=========================
'=========================
Sub Assign_Gen_Code
'===========================================================
'=== THE ALGORITHM FOR THE ASSIGNMENT OF A ONE-CHARACTER
'=== NON-BLANK IDENTIFIER TO EACH ACTIVATION FRONT WILL CYCLE
'=== ORDERLY AMONG THE CHARACTERS OF THE FOLLOWING STRING.
'=== CHARACTERS USED TO REPRESENT VALID STATE ARE EXCLUDED
'=== FROM THE STRING TO AVOID AMBIGUITIES.
'=== A RELATIVELY HIGH NUMBER OF DIFFERENT SYMBOLS IS USED TO
'=== ENSURE THAT A GIVEN IDENTIFIER WILL BE REPEATED ONLY MORE
'=== THAN 50 POSITIONS AWAY FROM ANY GIVEN GENERATORS.
'=== CONSIDERING THAT THE SYMBOL WILL BE USED TO SELECTIVELY
'=== INACTIVATE A FRONT ON COLLISION OR ON EXPIRATION OF THE
'=== REQUIRED FIRE CYCLES, IT IS MANDATORY THAT TWO COLLIDING
'=== FRONTS HAVE DIFFERENT ONE-CHARACTER IDENTIFIERS
'===========================================================
ORIGIN_CHAR_ID = "BCDEGHIJKLMNOPQRSTUVXYZbcdeghijklmnopqrstuvwxyz0123456789"
'===========================================================
'=== ALGORITHM FOR THE ASSIGNMENT OF A ONE-CHARACTER
'=== NON-BLANK IDENTIFIER «GenCode» TO EACH GENERATOR
'=== It will propagate to all the generators of the same «activation wave»
'===========================================================
For i = 1 To 500
if Math.Remainder(i,57) = 0 then
GenCode[i] = 9
else
GenCode[i] = Text.GetSubText(ORIGIN_CHAR_ID,Math.Remainder(i,57),1)
EndIf
EndFor
EndSub
'=====================================================
'=====================================================
' CHECK WHICH BUTTON WAS CLICKED AND TAKE SPECIFIC ACTIONS
'=====================================================
'=====================================================
Sub CheckButtons
'=====================================================
' BUTTONS TO DISPLAY HELP TEXTS
'=====================================================
If ButtonCap = "DISCLAIMER & LICENSE" Then
Curr_Text = Disclaimer
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "THE CHEVRON PARADIGM" Then
Curr_Text = Paradigm
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "HOW TO USE" Then
Curr_Text = Explanations
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Wait Cycles" Then
Curr_Text = Expl_WAIT
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Fire Cycles" Then
Curr_Text = Expl_FIRE
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Generators Step" Then
Curr_Text = Expl_STEP
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Even/Random Init. + HS Delay" Then
Curr_Text = Expl_SUPERVISED
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Border Line" Then
Curr_Text = Expl_BORDER
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Flammule Filling" Then
Curr_Text = Expl_FIFLA
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Collision Control" Then
Curr_Text = Expl_COLLISION
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Reticulation" Then
Curr_Text = Expl_RETIC
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Unresponsive Band" Then
Curr_Text = Expl_UNRESPONSIVE
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Inhibition Range" Then
Curr_Text = Expl_RAINH
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Chevron Survival" Then
Curr_Text = Expl_CHSUR
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "N° Renderings" Then
Curr_Text = Expl_MXPSS
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
ElseIf ButtonCap = "Offset Rend." Then
Curr_Text = Expl_OFFRN
GraphicsWindow.ShowMessage(Curr_Text,ButtonCap)
'=====================================================
' MAIN BUTTONS - INPUT PARAMETERS, GENERATE AND CLOSE
'=====================================================
ElseIf ButtonCap = "1) INPUT PARAMETERS (OR SELECT PRESET)" Then
Ask_Parameters()
'--------------------------------------------------------------------------------------------------------------------------------'
' GENERATE Button - Rendering-specific initializations should go here
'--------------------------------------------------------------------------------------------------------------------------------'
ElseIf ButtonCap = "2) GENERATE" Then
Generate()
ElseIf ButtonCap = "CLOSE PROGRAM" Then
Program.End()
'=====================================================
' BUTTONS TO SELECT ONE OF THE SIX AVAILABLE PRESETS
'=====================================================
ElseIf ButtonCap = "Select 1" Then
Preferred_Preset = 1
Choose_Preset()
ElseIf ButtonCap = "Select 2" Then
Preferred_Preset = 2
Choose_Preset()
ElseIf ButtonCap = "Select 3" Then
Preferred_Preset = 3
Choose_Preset()
ElseIf ButtonCap = "Select 4" Then
Preferred_Preset = 4
Choose_Preset()
ElseIf ButtonCap = "Select 5" Then
Preferred_Preset = 5
Choose_Preset()
ElseIf ButtonCap = "Select 6" Then
Preferred_Preset = 6
Choose_Preset()
'=====================================================
' BUTTONS DISPLAYING AN EXAMPLE RENDERING FOR EACH PRESET
'=====================================================
ElseIf ButtonCap = "SHOW EXAMPLE 1" Then
ImageName=ImageName1
ImgMsgTitle = Name_Example[1]
ImgMsgText = Descr_Example[1]
Show_Example()
ElseIf ButtonCap = "SHOW EXAMPLE 2" Then
ImageName=ImageName2
ImgMsgTitle = Name_Example[2]
ImgMsgText = Descr_Example[2]
Show_Example()
ElseIf ButtonCap = "SHOW EXAMPLE 3" Then
ImageName=ImageName3
ImgMsgTitle = Name_Example[3]
ImgMsgText = Descr_Example[3]
Show_Example()
ElseIf ButtonCap = "SHOW EXAMPLE 4" Then
ImageName=ImageName4
ImgMsgTitle = Name_Example[4]
ImgMsgText = Descr_Example[4]
Show_Example()
ElseIf ButtonCap = "SHOW EXAMPLE 5" Then
ImageName=ImageName5
ImgMsgTitle = Name_Example[5]
ImgMsgText = Descr_Example[5]
Show_Example()
ElseIf ButtonCap = "SHOW EXAMPLE 6" Then
ImageName=ImageName6
ImgMsgTitle = Name_Example[6]
ImgMsgText = Descr_Example[6]
Show_Example()
'=====================================================
' BUTTONS SHOWING THE DESCRIPTION OF THE SIX PRESETS
'=====================================================
ElseIf ButtonCap = "Descr. 1" Then
GraphicsWindow.ShowMessage(Descr_Example[1],Name_Example[1])
ElseIf ButtonCap = "Descr. 2" Then
GraphicsWindow.ShowMessage(Descr_Example[2],Name_Example[2])
ElseIf ButtonCap = "Descr. 3" Then
GraphicsWindow.ShowMessage(Descr_Example[3],Name_Example[3])
ElseIf ButtonCap = "Descr. 4" Then
GraphicsWindow.ShowMessage(Descr_Example[4],Name_Example[4])
ElseIf ButtonCap = "Descr. 5" Then
GraphicsWindow.ShowMessage(Descr_Example[5],Name_Example[5])
ElseIf ButtonCap = "Descr. 6" Then
GraphicsWindow.ShowMessage(Descr_Example[6],Name_Example[6])
EndIf
EndSub
'=====================================================
'=====================================================
' CHOOSE A PRESET (ACTIVATED BY CLICK ON BUTTONS)
'=====================================================
'=====================================================
Sub Choose_Preset
Clear_And_Hide_Controls()
If Preferred_Preset = 1 Then
Min_Wait_Cycles = 18
Max_Wait_Cycles = 24
Min_Fire_Cycles = 18
Max_Fire_Cycles = 35
Step_Size_Px = 45
Evenness = "R"
HALFSTEP_DELAY = "N"
RANGE_INHIB = 8
Mark_Inact_Front = "Y"
FillFlam = "Y"
Collision_Check = "Y"
Reticulation = "N"
ChevSurv = "N"
Unresponsive_Band = 0
MAX_PASSES = 3
ElseIf Preferred_Preset = 2 Then
Min_Wait_Cycles = 30
Max_Wait_Cycles = 40
Min_Fire_Cycles = 10
Max_Fire_Cycles = 20
Step_Size_Px = 60
Evenness = "E"
HALFSTEP_DELAY = "Y"
RANGE_INHIB = 2
Mark_Inact_Front = "N"
FillFlam = "N"
Collision_Check = "N"
Reticulation = "Y"
ChevSurv = "Y"
Unresponsive_Band = 0
MAX_PASSES = 1
ElseIf Preferred_Preset = 3 Then
Min_Wait_Cycles = 20
Max_Wait_Cycles = 35
Min_Fire_Cycles = 20
Max_Fire_Cycles = 30
Step_Size_Px = 60
Evenness = "R"
HALFSTEP_DELAY = "N"
RANGE_INHIB = 8
Mark_Inact_Front = "N"
FillFlam = "N"
Collision_Check = "Y"
Reticulation = "N"
ChevSurv = "N"
Unresponsive_Band = 0
MAX_PASSES = 1
ElseIf Preferred_Preset = 4 Then
Min_Wait_Cycles = 10
Max_Wait_Cycles = 25
Min_Fire_Cycles = 8
Max_Fire_Cycles = 18
Step_Size_Px = 40
Evenness = "R"
HALFSTEP_DELAY = "N"
RANGE_INHIB = 2
Mark_Inact_Front = "Y"
FillFlam = "Y"
Collision_Check = "N"
Reticulation = "N"
ChevSurv = "N"
Unresponsive_Band = 0
MAX_PASSES = 1
ElseIf Preferred_Preset = 5 Then
Min_Wait_Cycles = 16
Max_Wait_Cycles = 30
Min_Fire_Cycles = 18
Max_Fire_Cycles = 24
Step_Size_Px = 60
Evenness = "R"
HALFSTEP_DELAY = "N"
RANGE_INHIB = 2
Mark_Inact_Front = "Y"
FillFlam = "Y"
Collision_Check = "N"
Reticulation = "Y"
ChevSurv = "N"
Unresponsive_Band = 0
MAX_PASSES = 1
ElseIf Preferred_Preset = 6 Then
Min_Wait_Cycles = 10
Max_Wait_Cycles = 30
Min_Fire_Cycles = 24
Max_Fire_Cycles = 30
Step_Size_Px = 50
Evenness = "E"
HALFSTEP_DELAY = "Y"
RANGE_INHIB = 2
Mark_Inact_Front = "Y"
FillFlam = "Y"
Collision_Check = "N"
Reticulation = "N"
ChevSurv = "N"
Unresponsive_Band = 0
MAX_PASSES = 1
EndIf
Reset_And_Show_Controls()
'===================> Graphics Window is not self-clearing
'===================> new values will be overwritten above
'===================> existing values, unless cleared
GraphicsWindow.BrushColor=GraphicsWindow.BackgroundColor
GraphicsWindow.FillRectangle(538,170, 25, 500)
GraphicsWindow.BrushColor="Green"
GraphicsWindow.FontSize = 16
GraphicsWindow.DrawText(540,175, Min_Wait_Cycles)
GraphicsWindow.DrawText(540,201, Max_Wait_Cycles)
GraphicsWindow.DrawText(540,230, Min_Fire_Cycles)
GraphicsWindow.DrawText(540,256, Max_Fire_Cycles)
GraphicsWindow.DrawText(540,290, Step_Size_Px)
GraphicsWindow.DrawText(540,330, Evenness)
GraphicsWindow.DrawText(555,330, HALFSTEP_DELAY)
GraphicsWindow.DrawText(540,370, Mark_Inact_Front)
GraphicsWindow.DrawText(540,410, FillFlam)
GraphicsWindow.DrawText(540,450, Collision_Check)
GraphicsWindow.DrawText(540,490, Reticulation)
GraphicsWindow.DrawText(540,530, Unresponsive_Band)
GraphicsWindow.DrawText(540,570, RANGE_INHIB)
GraphicsWindow.DrawText(540,610, ChevSurv)
GraphicsWindow.DrawText(540,650, MAX_PASSES)
GraphicsWindow.DrawText(540,690, OFFSET)
GraphicsWindow.DrawText(275,650,"NUMBER OF RENDERINGS")
Controls.ShowControl(GENRT)
EndSub
'=====================================================
'=====================================================
' CLEAR GRAPHICS WINDOW AND HIDE CONTROLS
'=====================================================
'=====================================================
Sub Clear_And_Hide_Controls
Controls.HideControl(DISCL)
Controls.HideControl(CHEVR)
Controls.HideControl(HOWTO)
Controls.HideControl(WAITC)
Controls.HideControl(FIREC)
Controls.HideControl(GSTEP)
Controls.HideControl(EVENR)
Controls.HideControl(BRDRL)
Controls.HideControl(FIFLA)
Controls.HideControl(COLLC)
Controls.HideControl(RETIC)
Controls.HideControl(UNREB)
Controls.HideControl(RAINH)
Controls.HideControl(CHSUR)
Controls.HideControl(MXPSS)
Controls.HideControl(OFFRN)
Controls.HideControl(INPUT)
Controls.HideControl(CLOSE)
Controls.HideControl(GENRT)
Controls.HideControl(SELCT1)
Controls.HideControl(SELCT2)
Controls.HideControl(SELCT3)
Controls.HideControl(SELCT4)
Controls.HideControl(SELCT5)
Controls.HideControl(SELCT6)
Controls.HideControl(DESCR1)
Controls.HideControl(DESCR2)
Controls.HideControl(DESCR3)
Controls.HideControl(DESCR4)
Controls.HideControl(DESCR5)
Controls.HideControl(DESCR6)
Controls.HideControl(SHOWEX1)
Controls.HideControl(SHOWEX2)
Controls.HideControl(SHOWEX3)
Controls.HideControl(SHOWEX4)
Controls.HideControl(SHOWEX5)
Controls.HideControl(SHOWEX6)
GraphicsWindow.BrushColor=GraphicsWindow.BackgroundColor
GraphicsWindow.FillRectangle(0,0,1400,800)
EndSub
'=========================
'=========================
' GENERATE RENDERING
'=========================
'=========================
Sub Generate
Clear_And_Hide_Controls()
'------------------------> DEBUG start
If DEBUG then '-> DEBUG
TextWindow.Clear() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG ends
'--------------------------------------------------------------------------------------------------------------------------------'
' Display Rendering Parameters
'--------------------------------------------------------------------------------------------------------------------------------'
GraphicsWindow.FontName="Roboto"
GraphicsWindow.FontSize = 14
GraphicsWindow.BrushColor = "Black"
'Current parameters will be shown above the graphics
GraphicsWindow.DrawText(0,0,Clock.Day+"/"+Clock.Month+"/"+(Clock.Year-2000)+" "+Clock.Time+" -V"+Version+" -WMin "+Min_Wait_Cycles+" -WMax "+Max_Wait_Cycles+" -FMin "+Min_Fire_Cycles+" -FMax "+Max_Fire_Cycles+" -Step "+Step_Size_Px+" -EVN "+Evenness+" -HSD "+HALFSTEP_DELAY+" -RInh "+RANGE_INHIB+" -FullBrdr "+Mark_Inact_Front+" -FillFl "+FillFlam+" -CollChk "+Collision_Check+" -RetENA "+Reticulation+" -ChvSrv "+ChevSurv+" -BlkBnd "+Unresponsive_Band+" -MaxP "+MAX_PASSES)
'--------------------------------------------------------------------------------------------------------------------------------'
' Multiple Renderings Initialization
'--------------------------------------------------------------------------------------------------------------------------------'
PASSES = 1 'this will be the first full rendering
CYCLE_OFFSET = 0 ' no offset
Flammule_BKG_Color = BkgColor[1]
OneMoreGeneration:
'***************************************************************
'************** COLOR INITIALIZATION ***********************
'***************************************************************
If FillFlam = "N" Then
Flammule_BKG_Color = GeneralBackgroundColor
EndIf
'***************************************************************
'************** VECTOR INITIALIZATION **********************
'************* Regardless of "Evenness" setting ******************
'***************************************************************
' The three Subroutines:
' - Set_Required_Wait_Cycles()
' - Set_Required_Fire_Cycles()
' have built-in control of the Evenness setting.
' If Evenness=Y, the corresponding value will be set at the minimum
' value input by user, otherwise it will be randomly selected between
' minimum and maximum value
For i = 1 To 500
' RANDOMIZE or SET Required_Wait_Cycles for all the Generators...
WhichGen = i
Set_Required_Wait_Cycles()
'=========================================================
'===========> Last Wait Cycle is calculated and assigned
'===========> to the generator.
'===========> Initialize current FIRE cycles is NOT NEEDED!!! It will be
'===========> initialized to 0 as soon as WAIT is complete.
'===========> Considering that the loop will initiate with OP_ITERATION 1,
'===========> Last Wait Cycle = Required Wait Cycles
'=========================================================
Last_Wait_Cycle[i] = Required_Wait_Cycles[i]
' RANDOMIZE or SET Required_Fire_Cycles for all the Generators...
WhichGen = i
Set_Required_Fire_Cycles()
'=========================================================
'===========> Last Fire Cycle is calculated and assigned
'===========> to the generator.
'===========> Considering that the loop will initiate with OP_ITERATION 1,
'===========> Last Fire Cycle = Required Wait Cycles + Required Fire Cycles
'=========================================================
Last_Fire_Cycle[i] = Required_Wait_Cycles[i] + Required_Fire_Cycles[i]
'WhichColor should be initialized to the "flammule border" (chevron) color
WhichColor[i] = Flammule_LINE_Color
'LastBorderState[] and NextBorderState[] are used for reticulation, if required
LastBorderState[i] = "*"
NextBorderState[i] = "*"
'Cycle_Activated may help understanding which colliding front is younger
'(the younger front overlaps the older front)
Cycle_Activated[i] = 0
'Monitor_Fire_Expired is the number of the Generator that initiated a propagation
'front. all the Generators in the front will monitor the expiration of fire cycles of their
'initial promoter
Monitor_Fire_Expired[i] = 0
EndFor
'=======================================
' With the vectors fully initialized, I will just need to
' set specific values when needed
'=======================================
'***************************************************************
'***************************************************************
'************** RANDOM INITIALIZATION *********************
'***************************************************************
'***************************************************************
If Evenness = "R" Then
'*=====> HERE WHEN the user has chosen RANDOM settings
' for all the Generators, set:
' CURRENT Generator state «W» - WAIT
' NEXT Generator state «W» - WAIT
For i = 1 To 500
curr_prop_stat[i] = "W"
next_prop_stat[i] = "W"
Irreversible_W[i] ="False"
'====> UNLESS ACTIVATED, ActCode is "-" (a value
'====> non included among the available GenCode).
ActCode[i] = "-"
EndFor
' ============================================
' I need to use in a relaxed way the STEP provided by the user
'==================================================
' SET UP AN UNEVEN ARRAY OF PROPAGATING GENERATORS
'==================================================
'Initialize the position of the first «W» Generator
'NewPosition is initially set at around Step_Size_Px
RETRY_POSITION:
NewPosition = Math.GetRandomNumber(Math.Round(Step_Size_Px*1.15))
If NewPosition < Math.Round(Step_Size_Px*0.85) Then
Goto RETRY_POSITION
EndIf
'=======================================
' RANDOMIZE POSITION & INITIAL WAIT LATENCY
'=======================================
Initial_Wait = "SHORT"
For i = 1 To 500
' RANDOMIZE LAST WAIT CYCLE FOR ALL THE GENERATORS
' To increase the number of quickly activating Generators at startup,
' one may decide to initialize the LAST WAIT CYCLE to a value
' between 50% and 100% of the required cycles, to allow an uneven,
' semi- chaotic initial state of the growth edge
WhichGen=i
Randomize_Last_Wait_Cycle()
' PROPAGATING GENERATORS (state «F») are placed randomly
If i = NewPosition then
'*===> HERE WHEN the Generator at "NewPosition" is reached
' This is the position where an«F» GENERATOR must be placed.
next_prop_stat[i] = "F" ' FIRE - new, diverging propagation fronts
' Activation Code will be the GenCode of generator that activates the new front
ActCode[i] = GenCode[i]
'=========================================================
'===========> The chevron lines propagation used in the "reticulation control"
'===========> are initialized for propagation
'=========================================================
NextBorderState[i] = "B"
'=========================================================
'===========> The sensor will fire starting with OP_ITERATION 1 - reset its
'===========> LAST_FIRE_CYCLE to REQUIRED FIRE CYCLES
'=========================================================
WhichGen=i
Last_Fire_Cycle[i] = Required_Fire_Cycles[i]
'Monitor_Fire_Expired is the number of the Generator that initiated a propagation
'front. all the Generators in the front will monitor the expiration of fire cycles of their
'initial promoter
Monitor_Fire_Expired[i] = i
' I randomize a new position more or less centered on the desired step
'...NEW_STEP is randomized between 85% and 115% Step_Size_Px
Retry_New_Position:
NewStep = Math.GetRandomNumber(Math.Round(Step_Size_Px*1.15))
If NewStep < Math.Round(Step_Size_Px*0.85) Then
Goto Retry_New_Position
EndIf
' The position of the next «F» GENERATOR is set accordingly.
NewPosition = i + NewStep
'------------------------> DEBUG start
If DEBUG then '-> DEBUG
' show next_prop_stat[i] for debug purposes '-> DEBUG
TextWindow.Write(next_prop_stat[i]+" - (i="+i+") | ") '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG ends
EndIf
EndFor
'*******************************************************************
'*******************************************************************
'************** SUPERVISED INITIALIZATION *********************
'*******************************************************************
'*******************************************************************
Else
'*=====> HERE WHEN the user has chosen SUPERVISED settings
' for all the Generators, set:
' CURRENT propagation state «W» - WAIT
' NEXT propagation state «W» - WAIT
' State «W» is irreversible
For i = 1 To 500
curr_prop_stat[i] = "W"
next_prop_stat[i] = "W"
Irreversible_W[i] ="True"
'====> UNLESS ACTIVATED, ActCode is "-" (a value
'====> non included among the available GenCode).
ActCode[i] = "-"
EndFor
' ============================================
' I need to use RIGOROUSLY the STEP provided by the user
'==================================================
' SET UP AN EVEN ARRAY OF PROPAGATING GENERATORS
'==================================================
'==========================================================
' At the beginning of the initialization (see above),
' REQUIRED WAIT CYCLES was already set at a random value:
' !!!! MUST BE SET AT MINIMUM WAIT CYCLES FOR ALL THE GENERATORS !!!!
' REQUIRED FIRE CYCLES was already set at a random value:
' !!!! MUST BE SET AT MINIMUM FIRE CYCLES FOR ALL THE GENERATORS !!!!
'==========================================================
For i = 1 To 500
Required_Wait_Cycles[i] = Min_Wait_Cycles
Required_Fire_Cycles[i] = Min_Fire_Cycles
' For now, Spontaneous Activation is inhibited in all the Generators
' More under, inhibition will be removed from selected Generators
' Spontaneous Activation is inhibited by forcing an irreversible «W» state
Irreversible_W[i] ="True"
EndFor
'By default, next_prop_stat[] is «W» for all Generators.
'I just need to space the «F» Generators evenly
For i = Math.Round(Step_Size_Px/2) To 500 STEP Step_Size_Px
next_prop_stat[i] = "F" ' FIRE - new, diverging propagation fronts
'==================== The whole front is assigned the GenCode of its
'==================== first generator
ActCode[i] = GenCode[i]
'=========================================================
'===========> The chevron lines propagation used in the "reticulation control"
'===========> are initialized for propagation
'=========================================================
NextBorderState[i] = "B"
'=========================================================
'===========> The sensor will fire starting with OP_ITERATION 1 - reset its
'===========> LAST_FIRE_CYCLE to REQUIRED FIRE CYCLES
'=========================================================
WhichGen=i
Last_Fire_Cycle[i] = Required_Fire_Cycles[i]
'Monitor_Fire_Expired is the number of the Generator that initiated a propagation
'front. all the Generators in the front will monitor the expiration of fire cycles of their
'initial promoter
Monitor_Fire_Expired[i] = i
' Spontaneous Activation is re-enabled
Irreversible_W[i] ="False"
'------------------------> DEBUG start
'If DEBUG then '-> DEBUG
' Waitkey="False" '-> DEBUG
' Message_00="Generator ="+i+"- set «F» and Enabled Spontaneous Activation" '-> DEBUG
' MESSAGE_0_0_AND_WAIT() '-> DEBUG
'EndIf '-> DEBUG
'------------------------> DEBUG ends
EndFor
If HALFSTEP_DELAY = "Y" Then
' I un-inhibit evenly spaced generators midway between the «F» ones,
' they will not be inhibited and they will gain «F» state after Min_Wait_Cycles
For j = 1 To 500 STEP Step_Size_Px
next_prop_stat[j] = "W"
' Spontaneous Activation is re-enabled
Irreversible_W[J] ="False"
'------------------------> DEBUG start
'If DEBUG then '-> DEBUG
' Waitkey="False" '-> DEBUG
' Message_00="Generator ="+j+"- Enabled Spontaneous Activation" '-> DEBUG
' MESSAGE_0_0_AND_WAIT() '-> DEBUG
'EndIf '-> DEBUG
'------------------------> DEBUG ends
EndFor
Else
'==> HERE WHEN HALFSTEP_DELAY = "N"
'==> All the generators (both those at step and those at half step positions)
'==> should be immediately active
' I un-inhibit evenly spaced generators midway between the «F» ones,
' they will not be inhibited and they will gain «F» state after Min_Wait_Cycles
For j = 1 To 500 STEP Step_Size_Px
' SEE COMMENTS ABOVE in the For i = Math.Round(Step_Size_Px/2) To 500 STEP Step_Size_Px loop
next_prop_stat[j] = "F" ' FIRE - new, diverging propagation fronts
ActCode[j] = GenCode[j]
NextBorderState[j] = "B"
WhichGen=j
Last_Fire_Cycle[j] = Required_Fire_Cycles[j]
Monitor_Fire_Expired[j] = j
Irreversible_W[j] ="False"
'------------------------> DEBUG start
'If DEBUG then '-> DEBUG
' Waitkey="False" '-> DEBUG
' Message_00="Generator ="+i+"- set «F» and Enabled Spontaneous Activation" '-> DEBUG
' MESSAGE_0_0_AND_WAIT() '-> DEBUG
'EndIf '-> DEBUG
'------------------------> DEBUG ends
EndFor
EndIf ' END IF HALFSTEP_DELAY
EndIf ' END IF EVENNESS "R" or "E"
'------------------------> DEBUG start
If DEBUG then '-> DEBUG
For i = 1 To 50 '-> DEBUG
TextWindow.Write("P ="+i+"-") '-> DEBUG
TextWindow.Write("NxPrStat = "+next_prop_stat[i]+"-") '-> DEBUG
TextWindow.Write("Act Code = "+ActCode[i]+"-") '-> DEBUG
TextWindow.Write("Mon Fire Exp = "+Monitor_Fire_Expired[i]+"-") '-> DEBUG
TextWindow.Write("LastWaitCycle = "+Last_Wait_Cycle[i]+"-") '-> DEBUG
TextWindow.Write("LastFireCycle = "+Last_Fire_Cycle[i]+"-") '-> DEBUG
TextWindow.Write("Irreversible_W = "+Irreversible_W[i]+" | ") '-> DEBUG
TextWindow.WriteLine(" P ="+i+"-") '-> DEBUG
EndFor '-> DEBUG
TextWindow.WriteLine("Enter") '-> DEBUG
TextWindow.Read() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG ends
'------------------------> DEBUG start
'If DEBUG then '-> DEBUG
' '===========================================================
' '=== CHECK THE ALGORITHM FOR THE ASSIGNMENT OF A ONE-CHARACTER
' '=== NON-BLANK IDENTIFIER TO EACH ACTIVATION FRONT
' '===========================================================
' For i = 1 To 500 '-> DEBUG
' TextWindow.WriteLine("GenCode "+i+" = >"+GenCode[i]+"<, ActCode "+i+" = >"+ActCode[i]+"<") '-> DEBUG
' EndFor '-> DEBUG
' TextWindow.WriteLine("Enter") '-> DEBUG
' TextWindow.Read() '-> DEBUG
'EndIf '-> DEBUG
'------------------------> DEBUG ends
'=============================================================
' ========= Whichever the SETUP, if opted for non-trasmissive band ===========
' ========= I set the state of the Generators correspondingly ===========
'=============================================================
If Unresponsive_Band > 0 then
Start_from = 250 - Math.Round(Unresponsive_Band/2)
' Generators in state «A» will not react to propagation and will not change state
For Delete_generator = Start_from To (Start_from + Unresponsive_Band)
curr_prop_stat[Delete_generator] = "A"
next_prop_stat[Delete_generator] = "A"
EndFor
EndIf
'=============================================
'Regardless of the presets, the upmost and the downmost
'generators cannot propagate nor change state
'=============================================
For i = 1 To 3
curr_prop_stat[i] = "A"
next_prop_stat[i] = "A"
EndFor
For i = 498 To 500
curr_prop_stat[i] = "A"
next_prop_stat[i] = "A"
EndFor
'window size 1200
'prograde x=30
'retrograde:
x=1200
y=30
'Draw the initial propagation front
For PixelDraw = 1 To 500
If curr_prop_stat[PixelDraw] = "F" Then
' If the «iteration» loop has step 2, I can draw each dot twice
'prograde GraphicsWindow.SetPixel(x+1,y+PixelDraw,"white")
'prograde GraphicsWindow.SetPixel(x+2,y+PixelDraw,"white")
'retrograde:
GraphicsWindow.SetPixel(x-1,y+PixelDraw,"white")
GraphicsWindow.SetPixel(x-2,y+PixelDraw,"white")
EndIf
EndFor
'------------------------> DEBUG start
If DEBUG then '-> DEBUG
For act_num = 1 to 75
TextWindow.CursorLeft = 1 '-> DEBUG
TextWindow.CursorTop = 1+act_num '-> DEBUG
TextWindow.Write(act_num+") ") '-> DEBUG
EndFor '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG END
'===========================================
' "Propagation"
' In the For loop, Step 2 is set to allow
' marking each activation with a double
' point, for better readability
'===========================================
'==============\
'===============> MAIN PROGRAM CYCLE starts
'==============/
For iteration = 3 + CYCLE_OFFSET To 1000 Step 2 '3 to 1000
' =======================================
' OPERATIONAL ITERATION - Explanation
'-------------------------------------------------------------------
' The Main program Cycle increases the variable
' "iteration", in odd values at step 2. As an example, its
' values in tye first cycles are: 3 - 5 - 7 - 9 - 11 - 13.....
' For a proper usage in calculations including the
' number of expired fire and wait cycles, I need a different
' value, here called OP_ITERATION, that increases of
' single units. Its values corresponding to the example
' above in tye first cycles are: 1 - 2 - 3 - 4 - 5 - 6.........
' In other words, OP_ITERATION is the MAIN CYCLE COUNTER
' =======================================
OP_ITERATION = (((iteration - CYCLE_OFFSET) - 1)/2)
'------------------------> DEBUG START
If DEBUG then '-> DEBUG
'TextWindow.Read() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG END
'===============================
' the vector CURR_PROP_STAT used to
' control the current propagation cycle is
' fed with the contents of NEXT_PROP_STAT
'===============================
For aaa = 1 To 500
curr_prop_stat[aaa] = next_prop_stat[aaa]
EndFor
'===============================
' the vector LAST BORDER STATE used to
' control the propagation of chevron lines is
' fed with the contents of NEXT BORDER STATE
'===============================
For aaa = 1 To 500
LastBorderState[aaa] = NextBorderState[aaa]
EndFor
'===============================
' the vector Mark_Inactive used to draw a
' line whenever a propagation front is stopped
' is initialized as false
'===============================
For aaa = 1 To 500
Mark_Inactive[aaa] = "False"
EndFor
'===============================
' make UNRESPONSIVE the top three and
' the bottom three lines
'===============================
For aaa = 1 To 3
curr_prop_stat[aaa] = "A"
EndFor
For aaa = 498 To 500
curr_prop_stat[aaa] = "A"
EndFor
'=================================
' P R O P A G A T I O N
'=================================
' The algorithm is based on two vectors with 500
' elements each, representing:
' - curr_prop_stat[] - propagation state (current cycle)
' - next_prop_stat[] - propagation state (next cycle)
'-----------------------------------------------------------
' One Generator at a time, its current propagation
' state is examined.
' Next propagation state is defined according
' to the following rules:
'
' 1) If current state is «W» (=WAIT), wait count is
' increased and checked against required wait
' duration. If not reached, the Generator remains in state «C»
' Otherwise, UNLESS INHIBITED, spontaneous activation takes place,
' meaning that the Generator enters state «F».
' If spontaneous activation is inhibited, the Generator
' remains in state «W» indefinitely.
' 2) If current state is «F», NEXT STATE of the Generator
' ABOVE will be «F», NEXT STATE of the Generator
' BELOW will be «F». This is a bi-directional «activation wave».
' Propagation may take place only under two conditions:
' A) the target Generator (above or below the current
' generator) must be in state «W»;
' B) no COLLISION is imminent in the direction of
' propagation.
' If propagation is impossible, after writing a dot,
' the current Generator is reset to «W».
' If propagation is possible, fire count is increased
' and checked against required fire duration.
' If required fire duration is reached, the generator
' enters «W» (=WAIT) state with wait count=0.
' Otherwise, the Generator remains in state «F»
' 3) whenever propagation waves encounter, in other words,
' whenever an attempt is made at setting ON («F»)
' a Generator that is already ON («F»), a COLLISION
' takes place. According to the principle of mutual elision of
' converging «activation waves», all the offending Generators
' are reset to «C». Collision control must be PROACTIVE, to
' intercept oncoming ( = two generators away ) propagation
' waves
'------------------------> DEBUG start
'If DEBUG Then '-> DEBUG
' TextWindow.Write("Press Enter") '-> DEBUG
' TextWindow.Read() '-> DEBUG
'EndIf '-> DEBUG
'------------------------> DEBUG END
'==============\
'===============> CHECK PROPAGATION LOOP STARTS
'==============/
For curr_Generator = 1 To 500 '1 to 500
If OP_ITERATION > 40 and curr_Generator = 52 Then '-> DEBUG
'--------------> Which Generator should be observed to understand whether the Current Generator should stop firing?
Where_To_Check_Expiration = Monitor_Fire_Expired[curr_Generator]
'--------------> Which cycle is the LAST FIRE CYCLE for the current Generator?
MyLastFireCycle = Last_Fire_Cycle[Where_To_Check_Expiration]
'------------------------> DEBUG start
'If DEBUG Then '-> DEBUG
' TextWindow.CursorTop = 0 '-> DEBUG
' TextWindow.CursorLeft = 0 '-> DEBUG
' TextWindow.Write("CURR_GENERATOR = 52 - curr_prop_stat[curr_Generator] "+ curr_prop_stat[curr_Generator] + " next_prop_stat[curr_Generator] "+ next_prop_stat[curr_Generator]) '-> DEBUG
' TextWindow.Write("activation code "+ ActCode[curr_Generator]+ " OP_ITERATION " +OP_ITERATION +" MyLastFireCycle " +MyLastFireCycle + " ") '-> DEBUG
' TextWindow.Read() '-> DEBUG
'EndIf '-> DEBUG
'------------------------> DEBUG END
EndIf
'============================================
'============================================
'============================================
' RETICULATION(=VISUALIZATION OF CHEVRON
' LINES) CONTROL
'============================================
This_Generator = curr_Generator
Manage_Reticulation()
'============================================
'============================================
'============================================
' END RETICULATION CONTROL
'============================================
'============================================
'============================================
'------------------------> DEBUG start
If DEBUG Then '-> DEBUG
' Show Cycle Count '-> DEBUG
Waitkey="False"
Message_00="Iteration "+OP_ITERATION+", Generator "+curr_Generator '-> DEBUG
MESSAGE_0_0_AND_WAIT() '-> DEBUG
Update_Debug_Line()
EndIf '-> DEBUG
'------------------------> DEBUG END
' for ease of reading, I park curr_prop_stat[curr_Generator]
' in a shortly-named variable
ActState = curr_prop_stat[curr_Generator]
'=====================================
'=====================================
'
' *********
' ***** *****
' ***** *****
' ***** *****
' ***** *****
' *****************************
' *********************************
' **********************************
' ****** ******
' ****** ******
' ****** ******
' ****** ******
'
'=====================================
'=====================================
' GENERATOR state «A» - ABSENT
' - DO NOTHING
' - REMAIN IN STATE
'=====================================
'=====================================
'
If ActState = "A" Then
next_prop_stat[curr_Generator] = "A"
'=====================================
'=====================================
' GENERATOR state «F» - FIRE
' - Generate two activation waves, one
' «U», and one «D»
' - Continue propagation until latency expired
' or collision
'=====================================
'=====================================
'
'=====================================
'=====================================
'
' *******************************
' *******************************
' *******************************
' ******
' ******
' ******
' *******************************
' *******************************
' *******************************
' ******
' ******
' ******
' ******
' ******
'
'=====================================
'=====================================
ElseIf ActState = "F" Then
'=========================================================
' A logical error persists and proved impossible to prevent despite in-depth debug:
' exceptionally, activation may be attempted for a Generator that inherited
' active state from propagation, but somehow lost its activation code.
' Similar problems were observed in collisions with freshly-activated Generators
' at the tip of the chevrons, and were completely solved by redefing the scope of
' the propagation front reset routine.
' Until present time, measures to avoid this exceptional error had undesirable
' effects and , although successful, didn't exhaustively demonstrate that the
' problem was forever solved. As a provisional patch before more extensive
' re-engeneering, any such offending sensor is simply reset to «W» state.
'=========================================================
If ActCode[curr_Generator] = " " Or ActCode[curr_Generator] = "-" then
'------------------------> DEBUG start
If DEBUG Then '-> DEBUG
Sound.PlayBellRing()
Waitkey="True" '-> DEBUG
Message_00="Line 1119 - F GENERATOR WITH ActCode["+curr_Generator+"] = >"+ActCode[curr_Generator]+"< !!!!!!!!!" '-> DEBUG
MESSAGE_0_0_AND_WAIT() '-> DEBUG
EndIf
'------------------------> DEBUG end
WhichGen=curr_Generator
Reset_Curr_Gen_State()
WhichGen=curr_Generator
Reset_Next_Gen_State()
EndIf
'-----------------------------------------------------------------------
' Unless the front is inactivated by collisions (and this may
' happen only when collision control is enforced), the
' current generator (for now...) may freely propagate
'-----------------------------------------------------------------------
Propagate = "True"
'=========================================
'=========================================
' SPONTANEOUS (OR FORCED) INACTIVATION CHECK
'=========================================
'=========================================
'-------------------------------------------------------------------------------------------------------------------------------------------
' Cause of spontaneous inactivation: LAST FIRE CYCLE of the originator/promoter generator in the front is
' reached - all the generators in a front inherit their LAST FIRE CYCLE fron the generator that initiated the front.
' If collision control is activated and collisions occur, the LAST FIRE CYCLE of the propagation wave to disable is
' set to OP_ITERATION + 1, so that at next cycle OP_ITERATION will be equal to Last_Fire_Cycle[curr_Generator].
' As a consequence, check for inactivation is performed in three steps:
' ... find in Monitor_Fire_Expired[curr_Generator] the number of the originator
' ... look for last fire c
' See collision control more under for further explanations
'-------------------------------------------------------------------------------------------------------------------------------------------
'--------------> Which Generator should be observed to understand whether the Current Generator should stop firing?
Where_To_Check_Expiration = Monitor_Fire_Expired[curr_Generator]
'--------------> Which cycle is the LAST FIRE CYCLE for the current Generator?
MyLastFireCycle = Last_Fire_Cycle[Where_To_Check_Expiration]
If OP_ITERATION >= MyLastFireCycle Then
'------------------------> DEBUG start
If DEBUG And curr_Generator < 76 Then '-> DEBUG
Sound.PlayClick()
Waitkey="True" '-> DEBUG
Message_00="Line 1162 Gen "+curr_Generator+" - Check exp Gen "+ Where_To_Check_Expiration+" - Found Last F_Cy "+ MyLastFireCycle + " reached at iteration "+ OP_ITERATION '-> DEBUG
MESSAGE_0_0_AND_WAIT() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG end
Propagate = "False"
WhichGen=curr_Generator
Reset_Curr_Gen_State()
WhichGen=curr_Generator
Reset_Next_Gen_State()
'-------------------------------------------------------------
' Terminate propagation front by a continuous line
'-------------------------------------------------------------
If Mark_Inact_Front = "Y" Then
Mark_Inactive[WhichGen] = "True"
EndIf
Else ' ELSE FIRE CYCLES NOT EXPIRED
' ============================================================================
' ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE!
' ============================================================================
' HERE WHEN COLLISION CHECK ACTIVE!!!!!!!!!!!!
' ============================================================================
' ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE! ACTIVE!
' ============================================================================
If Collision_Check = "Y" Then
'=====================================
'=====================================
' COLLISION SCREEN TOP / SCREEN BOTTOM
'=====================================
'=====================================
If curr_Generator < 5 or curr_Generator > 496 Then
'----------------------------------------------------------------------------------------------------------------------------
' The propagation wave that includes the current generator should be inactivated.
' Inactivation is a 2-step process:
' Step 1) Find the number of the generator that initiated of the wave, from Monitor_Fire_Expired[]
' Step 2) Set Last_Fire_Cycle of that generator to OP_ITERATION +1, so that, at next cycle, every Generator
' in the same front (=monitoring the very same generator) will reset for expiration of fire cycles.
'----------------------------------------------------------------------------------------------------------------------------
Propagate = "False"
Declare_Expired = Monitor_Fire_Expired[curr_Generator]
Last_Fire_Cycle[Declare_Expired] = OP_ITERATION + 1
'------------------------> DEBUG start
If DEBUG And curr_Generator < 76 Then '-> DEBUG
Waitkey="True" '-> DEBUG
Message_00="COLLISION SCREEN TOP/BTM "+curr_Generator+" Iter. " +OP_ITERATION+" - Declared expir. fire of Generator "+ Declare_Expired + " at "+ (OP_ITERATION + 1) +" cycles " '-> DEBUG
MESSAGE_0_0_AND_WAIT() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG end
Else
'=====================================
'=====================================
' COLLISION ELSEWHERE
'=====================================
'=====================================
' ==================================================================================
' DEFINITION OF COLLISION: contact between fronts originated by different generators
' ==================================================================================
' ------------------------------------------------------------------------------------------------------------------------------------
' COLLISION CONTROL ON - MANAGE COLLIDING FRONTS
'-------------------------------------------------------------------------------------------------------------------------------------
' One of the two colliding front should survive collision.
' An answer leading to acceptable and predicytable results is the following:
' The "older" front should survive. Any "younger"or "equal age" front should stop.
'
' To allow understanding which front is "younger", just a control of Cycle_Activated[curr_Generator] is needed
' -------------------------------------------------------------------------------------------------------------------------------------
' ==================================================================================
' Collision BELOW - the DOWNMOST generator is colliding. Waiting for contact would be too late for effective
' intervention - I should intercept it ONE STEP AWAY or TWO STEP AWAY
' ==================================================================================
Impending_collision = "False"
Position_below = 0
If Curr_prop_stat[curr_Generator+1] <> "F" And Curr_prop_stat[curr_Generator+2] <> "F" Then
If Curr_prop_stat[curr_Generator+3] = "F" Then
Impending_collision = "True"
Position_below = 3
EndIf
EndIf
If Curr_prop_stat[curr_Generator+1] <> "F" And Curr_prop_stat[curr_Generator+2] = "F" Then
Impending_collision = "True"
Position_below = 2
EndIf
If Curr_prop_stat[curr_Generator+1] = "F" And ActCode[curr_Generator+1] <> ActCode[curr_Generator] Then
Impending_collision = "True"
Position_below = 1
EndIf
If Impending_collision = "True" And Cycle_Activated[curr_Generator+Position_below] >= Cycle_Activated[curr_Generator] Then
'--------------------------------------------------------------------------------------------------------------------------------
' Apparently, there is no need to impede propagation of the current Generator!
' In fact, the conflicting Generator will be disabled, so the current Generator can prosecute its propagation.
'--------------------------------------------------------------------------------------------------------------------------------
'KEEP AS COMMENT: Propagate = "False"
'----------------------------------------------------------------------------------------------------------------------------
' Cycle_Activated[curr_Generator+1] >= Cycle_Activated[curr_Generator] means that curr_Generator
' began firing BEFORE than the colliding front ( = OLDER activation ) or AT THE SAME CYCLE
'----------------------------------------------------------------------------------------------------------------------------
' One of the colliding propagation waves should be inactivated.
' Inactivation is a 2-step process:
' Step 1) Find the number of the generator that initiated of the wave, from Monitor_Fire_Expired[]
' Step 2) Set Last_Fire_Cycle of that generator to OP_ITERATION +1, so that, at next cycle, every Generator
' in the same front (=monitoring the very same generator) will reset for expiration of fire cycles.
'----------------------------------------------------------------------------------------------------------------------------
'==============================================================================================
'= TO INHIBIT THE FRONT OF CURRENT GENERATOR:
'= Look for Monitor_Fire_Expired[curr_Generator] and Last_Fire_Cycle[Declare_Expired] = OP_ITERATION + 1
'= TO INHIBIT THE OTHER FRONT BELOW:
'= !!!!!!!!!NO!!!!!!!!!!!!!!!!!! It leads to recursive exension of Last_Fire_Cycle !!!!!!!!!!!!!!!!
'==============================================================================================
Declare_Expired = Monitor_Fire_Expired[curr_Generator]
Last_Fire_Cycle[Declare_Expired] = OP_ITERATION + 1
'------------------------> DEBUG start
If DEBUG And curr_Generator < 76 Then '-> DEBUG
Waitkey="True" '-> DEBUG
Message_00="COLLISION BELOW "+curr_Generator+" Iter. " +OP_ITERATION+" - Declared expir. fire of Generator "+ Declare_Expired + " at "+ (OP_ITERATION + 1) +" cycles " '-> DEBUG
MESSAGE_0_0_AND_WAIT() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG end
EndIf 'END IF Collision Below - younger wave detected
' ==================================================================================
' Collision ABOVE - the UPMOST generator is colliding
' ==================================================================================
Impending_collision = "False"
Position_above = 0
If Curr_prop_stat[curr_Generator-1] <> "F" And Curr_prop_stat[curr_Generator-2] <> "F" Then
If Curr_prop_stat[curr_Generator-3] = "F" Then
Impending_collision = "True"
Position_above = 3
'Propagate = "True"
EndIf
EndIf
If Curr_prop_stat[curr_Generator-1] <> "F" And Curr_prop_stat[curr_Generator-2] = "F" Then
Impending_collision = "True"
Position_above= 2
'Propagate = "True"
EndIf
If Curr_prop_stat[curr_Generator-1] = "F" And ActCode[curr_Generator-1] <> ActCode[curr_Generator] Then
Impending_collision = "True"
Position_above= 1
'Propagate = "False"
EndIf
If Impending_collision = "True" And Cycle_Activated[curr_Generator-Position_above] >= Cycle_Activated[curr_Generator] Then
'--------------------------------------------------------------------------------------------------------------------------------
' Apparently, there is no need to impede propagation of the current Generator!
' In fact, the conflicting Generator will be disabled, so the current Generator can prosecute its propagation.
'--------------------------------------------------------------------------------------------------------------------------------
'KEEP AS COMMENT: Propagate = "False"
'----------------------------------------------------------------------------------------------------------------------------
' Cycle_Activated[curr_Generator-1] >= Cycle_Activated[curr_Generator] means that curr_Generator
' began firing BEFORE ( = OLDER activation ) than the colliding front or AT THE SAME CYCLE
'----------------------------------------------------------------------------------------------------------------------------
' One of the colliding propagation waves should be inactivated.
' Inactivation is a 2-step process:
' Step 1) Find the number of the generator that initiated of the wave, from Monitor_Fire_Expired[]
' Step 2) Set Last_Fire_Cycle of that generator to OP_ITERATION +1, so that, at next cycle, every Generator
' in the same front (=monitoring the very same generator) will reset for expiration of fire cycles.
'----------------------------------------------------------------------------------------------------------------------------
'=============================================================================================
'= TO INHIBIT THE FRONT OF CURRENT GENERATOR:
'= Look for Monitor_Fire_Expired[curr_Generator] and Last_Fire_Cycle[Declare_Expired] = OP_ITERATION + 1
'= TO INHIBIT THE OTHER FRONT ABOVE:
'= !!!!!!!!!NO!!!!!!!!!!!!!!!!!! It leads to recursive exension of Last_Fire_Cycle !!!!!!!!!!!!!!!!
'=============================================================================================
Declare_Expired = Monitor_Fire_Expired[curr_Generator]
Last_Fire_Cycle[Declare_Expired] = OP_ITERATION + 1
'------------------------> DEBUG start
If DEBUG And curr_Generator < 76 Then '-> DEBUG
Waitkey="True" '-> DEBUG
Message_00="COLLISION ABOVE "+curr_Generator+" Iter. " +OP_ITERATION+" - Declared expir. fire of Generator "+ Declare_Expired + " at "+ (OP_ITERATION + 1) +" cycles " '-> DEBUG
MESSAGE_0_0_AND_WAIT() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG end
EndIf 'END IF Collision Above - younger wave detected
EndIf 'END IF Collision Check Screen Top / Screen Bottom / Elsewhere
Else ' ELSE IF Collision Check
' ==========================================================================
' INACTIVE! INACTIVE! INACTIVE! INACTIVE! INACTIVE! INACTIVE! INACTIVE! INACTIVE!
' ==========================================================================
' HERE WHEN COLLISION CHECK INACTIVE!!!!!!!!!!!!
' ==========================================================================
' INACTIVE! INACTIVE! INACTIVE! INACTIVE! INACTIVE! INACTIVE! INACTIVE! INACTIVE!
' ==========================================================================
' ----------------------------------------------------------------------------------------------------------------------------
' COLLISION CONTROL OFF - MANAGE OVERLAPPING FRONTS
'-----------------------------------------------------------------------------------------------------------------------------
' Even in case that collision is allowed, some rules are needed to answer the following question:
' which of the two colliding fronts "owns" the generators after the uncontrolled collision took place?
' An answer leading to acceptable and predicytable results is the following:
' The "younger" front should overlap the "older" front.
'
' To allow understanding which front is "younger", all the Generators in a front keep in the
' vector Cycle_Activated[] the number of the cycle when they were activated by the first Generator.
' On collision, the younger Generator passes its activation code, its activation cycle and its
' Monitor_Fire_Expired settings to the adjacent active generator.
'
' If the generators are of equal age, nothing happens. the two fronts will continue side by side until
' each front expires.
' ----------------------------------------------------------------------------------------------------------------------------
' =============================================
' =============================================
' Collision ABOVE - the generator ABOVE is colliding
'=============================================
' =============================================
If ActCode[curr_Generator-1] <> "-" And ActCode[curr_Generator] <> "-" Then
If Curr_prop_stat[curr_Generator-1] = "F" And ActCode[curr_Generator-1] <> ActCode[curr_Generator] Then
If Cycle_Activated[curr_Generator-1] > Cycle_Activated[curr_Generator] Then
'The current propagation front collided with a "younger" propagation front ABOVE.
'The current Generator inherits the activation code, the Cycle_Activated and the Monitor_Fire_Expired settings from the Generator ABOVE.
If JustChangedUP = "True" Then
ActCode [curr_Generator] = ActCode [curr_Generator-1]
Cycle_Activated[curr_Generator] = Cycle_Activated[curr_Generator-1]
Monitor_Fire_Expired[curr_Generator] = Monitor_Fire_Expired[curr_Generator-1]
'------------------------------------------------------------------------------------------------------------------------
' The state of the Generators is checked starting from the top, and going one step down at each cycle.
' This may lead to the unrestrained propagation of the colliding front above to EVERY generator in
' the current front. Instead of a chevron, gaining one Generator at each cycle, a vertical line would be
' drawn!
' To interrupt the propagation down after one instance, the logical flag JustChangedDOWN = "False"
' is provided. It will force one cycle of inaction before the next step of propagation down takes place.
'-------------------------------------------------------------------------------------------------------------------------
JustChangedUP = "False"
Else
JustChangedUP = "True"
EndIf
EndIf 'UNRESTRAINED COLLISION - Collision Above - younger wave detected
EndIf 'UNRESTRAINED COLLISION - Collision Above allowed with priority to the younger wave
EndIf ' END IF ActCode[curr_Generator-1] <> "-"
' =============================================
' =============================================
' Collision BELOW - the Generator BELOW is colliding
'=============================================
' =============================================
If ActCode[curr_Generator+1] <> "-" And ActCode[curr_Generator] <> "-" Then
If Curr_prop_stat[curr_Generator+1] = "F" And ActCode[curr_Generator+1] <> ActCode[curr_Generator] Then
If Cycle_Activated[curr_Generator+1] > Cycle_Activated[curr_Generator] Then
'The current propagation front collided with a "younger" propagation front BELOW.
'The current Generator inherits the activation code and the Cycle_Activated setting from the Generator BELOW.
ActCode [curr_Generator] = ActCode [curr_Generator+1]
Cycle_Activated[curr_Generator] = Cycle_Activated[curr_Generator+1]
Monitor_Fire_Expired[curr_Generator] = Monitor_Fire_Expired[curr_Generator+1]
EndIf 'UNRESTRAINED COLLISION - Collision Below - younger wave detected
EndIf 'UNRESTRAINED COLLISION - Collision Below allowed with priority to the younger wave
EndIf ' END IF ActCode[curr_Generator+1] <> "-"
EndIf ' END IF Collision Check
' ============================================================================
' COMPLETE! COMPLETE! COMPLETE! COMPLETE! COMPLETE! COMPLETE! COMPLETE!
' ============================================================================
' HERE WHEN COLLISION CHECK COMPLETE!!!!!!!!!!!!
' ============================================================================
' COMPLETE! COMPLETE! COMPLETE! COMPLETE! COMPLETE! COMPLETE! COMPLETE!
' ============================================================================
'==================================================
'==================================================
' HERE WHEN state «F» - CHECKS PERFORMED
'==================================================
'==================================================
'
' Propagate = "False" whenever a collision is detected
'
If Propagate = "True" Then
'=====================================
'=====================================
' HERE WHEN state «F»
' PROPAGATION NOT STOPPED
'=====================================
'=====================================
WhichGen=curr_Generator
Propagate_F_STATE()
EndIf ' END IF STOP PROPAGATION
EndIf ' END IF FIRE CYCLES NOT EXPIRED
'=====================================
'=====================================
'
' ****** ****** ******
' ****** ******** ******
' ****** ********* ******
' ****** ********** ******
' ****** *********** ******
' ****** ****** ****** ******
' ****** ****** ****** ******
' ****** ****** ****** ******
' ****** ****** ************
' *********** **********
'=====================================
'=====================================
'=====================================
'=====================================
' ACTIVATOR WAITING (status «W»)
' If Last_Wait_Cycle[] is reached,
' save exceptions!, the Generator enters state «F»
' otherwise the Generator remains «W»
'=====================================
'=====================================
'
ElseIf ActState = "W" Then
'===========================================
' Unless spontaneous activation is inhibited ...
'===========================================
If Irreversible_W[curr_Generator] = "True" Then
' Remain in state «W» - but remember that W is a TRASMISSIVE state!
' As such, it cannot overwrite «F» being propagated by up and down waves
If next_prop_stat[curr_Generator] <> "F" Then
next_prop_stat[curr_Generator] = "W"
EndIf
Else
'===========================================
' Spontaneous activation enabled
'===========================================
' Last Wait Cycle not reached
'===========================================
' If Last_Wait_Cycle is NOT reached by the current Generator,
' current Generator remains in state «W»
If OP_ITERATION < Last_Wait_Cycle[curr_Generator] Then
' *===> HERE WHEN Required_Wait_Cycles have NOT expired
' W state can propagate «activations waves»!!! Current Generator
' should maintain current status "W", unless a propagation wave
' has already changed next_prop_stat[curr_Generator]... which is
' perfectly legit.
' Considering that «W» is the default state of any Generator,
' if next_prop_stat[curr_Generator] <> "F", I can overwrite it
' with "W", but in any other case next_prop_stat[curr_Generator]
' shouldn't be modified! Otherwise, I would risk to stop a propagation
' wave by overwriting with «C» any legitimate «F» from adjacent
' Generators.
If next_prop_stat[curr_Generator] <> "F" Then
next_prop_stat[curr_Generator] = "W"
EndIf
'===========================================
' Spontaneous activation enabled
'===========================================
' Last Wait Cycle reached
'===========================================
Else
' ======================================================
' === ... UNLESS CURRENT GENERATOR IS AT THE TOP OR AT THE ====
' = BOTTOM OF THE SCREEN, in which case, the current generator is reset =
' ======================================================
all_ok_for_activation = "OK"
If curr_Generator = 4 or curr_Generator = 497 Then
all_ok_for_activation = "KO"
EndIf
' ======================================================
' === ... UNLESS THERE ARE ACTIVE ADJACENT GENERATORS!!!! =====
' === In which case, the current generator is reset to avoid excessive =====
' === conflicting activations / collisions / small spots ================
' ======================================================
' Check is performed considering the RANGE OF INHIBITION chosen by user
' ======================================================
For check_position = curr_Generator to curr_Generator - RANGE_INHIB Step -1
If next_prop_stat[check_position] = "F" Then
all_ok_for_activation = "KO"
EndIf
EndFor
For check_position = curr_Generator + 1 to curr_Generator + RANGE_INHIB
If next_prop_stat[check_position] = "F" Then
all_ok_for_activation = "KO"
EndIf
EndFor
If all_ok_for_activation = "OK" then
WhichGen = curr_Generator
Activate()
Else
'==> HERE WHEN current generator should not activate, e.g. because
'==> there is an active Generator nearby.
If next_prop_stat[curr_Generator] <> "F" Then
'===> ONLY WHEN THERE IS NO ADJACENT «F»
'===> the Generator is fully reset
WhichGen = curr_Generator
Reset_Next_Gen_State()
WhichGen = curr_Generator
Reset_Curr_Gen_State()
Else
'===> WHEN THERE IS AN ADJACENT «F»
'===> nothing should be done. At the time when
'===> next state of the current generator was set to «F»,
'===> all its parameters should have been set correctly
Nothing()
EndIf
EndIf ' End of the IF all ok for activation
EndIf ' End of the IF Cur_Wait_Cycles[curr_Generator] < Required_Wait_Cycles[curr_Generator]
EndIf ' END IF Irreversible_W[curr_Generator] = "True"
EndIf ' END IF ActState = «F» «C» «W»
PROPAGATION_LOOP_END:
'------------------------> DEBUG starts
'If DEBUG Then '-> DEBUG
' TextWindow.Write("OP_ITERATION= " + OP_ITERATION) '-> DEBUG
' TextWindow.WriteLine(" - curr_Generator= " + curr_Generator) '-> DEBUG
' For zzz = 20 To 60 '-> DEBUG
' TextWindow.Write(curr_prop_stat[zzz]+" ") '-> DEBUG
' EndFor '-> DEBUG
' answer=TextWindow.Read() '-> DEBUG
'EndIf '-> DEBUG
'------------------------> DEBUG ends
EndFor
'==============\
'===============> CHECK PROPAGATION LOOP ENDS
'==============/
'==========================================
' The following control should be unnecessary
'==========================================
If curr_Generator < 4 Or curr_Generator > 496 Then
WhichGen = curr_Generator
Reset_Curr_Gen_State()
WhichGen = curr_Generator
Reset_Next_Gen_State()
EndIf
'=========================
' Draw the new propagation front
'=========================
For PixelDraw = 1 To 500
If curr_prop_stat[PixelDraw] = "F" Or Mark_Inactive[PixelDraw] = "True" Then
' If opted for visible inactivation front and the generator
' was inactivated, draw point with Flammule_LINE_Color
If Mark_Inactive[PixelDraw] = "True" then
' If I am drawing a termination line, double vertical line seems much thicker than
' the side oblique lines of the flammule - so I will draw a double point only
' when I am NOT terminating a flammule
'prograde GraphicsWindow.SetPixel(x+iteration,y+PixelDraw,Flammule_LINE_Color)
'retrograde:
GraphicsWindow.SetPixel(x-iteration,y+PixelDraw,Flammule_LINE_Color)
Else
' It may be Flammule_BKG_Color or Flammule_LINE_Color
' depending on which generator must be drawn
If WhichColor[PixelDraw] = Flammule_LINE_Color Then
' When «Chevron Survival» = "Y" a misalignment of 1 pixel was observed between the chevrons
' of newly activated Generators and their "reticulation". For that reason, it was decided to omit
' chevron drawing whenever ChevSurv = "Y" - after all (see more under) the «reticulation»
' (chevron survival is an extension of reticulation) is an alternative to regular chevron
' generation.
If ChevSurv = "N" Then
' If the «iteration» loop has step 2, I can draw each dot twice
'prograde GraphicsWindow.SetPixel(x+iteration,y+PixelDraw,WhichColor[PixelDraw])
'prograde GraphicsWindow.SetPixel(x+iteration+1,y+PixelDraw,WhichColor[PixelDraw])
'retrograde:
GraphicsWindow.SetPixel(x-iteration,y+PixelDraw,WhichColor[PixelDraw])
GraphicsWindow.SetPixel(x-iteration-1,y+PixelDraw,WhichColor[PixelDraw])
EndIf
Else
' If the «iteration» loop has step 2, I can draw each dot twice
'prograde GraphicsWindow.SetPixel(x+iteration,y+PixelDraw,WhichColor[PixelDraw])
'prograde GraphicsWindow.SetPixel(x+iteration+1,y+PixelDraw,WhichColor[PixelDraw])
'retrograde:
GraphicsWindow.SetPixel(x-iteration,y+PixelDraw,WhichColor[PixelDraw])
GraphicsWindow.SetPixel(x-iteration-1,y+PixelDraw,WhichColor[PixelDraw])
EndIf
EndIf
'As long as "Flammule_LINE_Color" can be used just once, then reverts to "Flammule_BKG_Color"
' I can safely reset the color to "Flammule_BKG_Color"
WhichColor[PixelDraw] = Flammule_BKG_Color
EndIf
If curr_prop_stat[PixelDraw] = "A" and Unresponsive_Band > 0 Then
' If the «iteration» loop has step 2, I can draw each dot twice
'prograde GraphicsWindow.SetPixel(x+iteration,y+PixelDraw,"Gray")
'prograde GraphicsWindow.SetPixel(x+iteration+1,y+PixelDraw,"Gray")
'retrograde:
GraphicsWindow.SetPixel(x-iteration,y+PixelDraw,"Gray")
GraphicsWindow.SetPixel(x-iteration-1,y+PixelDraw,"Gray")
EndIf
'*=======================================================
'* IT MAY PROVE TOO COMPLICATE TO INTERCEPT ALGORITHMICALLY
'* ALL THE POSSIBLE CAUSES OF CONTOUR DISRUPTION.
'* IF THE POINT JUST DRAWN IS SANDWICHED BETWEEN A NON-«F»
'* GENERATOR AND AN «F» GENERATOR, IT'S ON THE MARGIN OF A
'* FLAMMULE AND SHOULD TAKE Flammule_LINE_Color
'*=======================================================
' When «Chevron Survival» = "Y" a misalignment of 1 pixel was observed between the chevrons
' of newly activated Generators and their "reticulation". For that reason, it was decided to omit
' chevron drawing whenever ChevSurv = "Y" - after all (see more under) the «reticulation»
' (chevron survival is an extension of reticulation) is an alternative to regular chevron
' generation.
If curr_prop_stat[PixelDraw] = "F" And ChevSurv = "N" Then
If WhichColor[PixelDraw] <> Flammule_LINE_Color Then
If curr_prop_stat[PixelDraw-1] <> "F" or curr_prop_stat[PixelDraw+1] <> "F" Then
'*==> HERE WHEN this Generator is in state «F» but one adjacent generator is not,
'*==> an indication that I am at the edge of a flammule
' If the «iteration» loop has step 2, I can draw each dot twice
'prograde GraphicsWindow.SetPixel(x+iteration,y+PixelDraw,Flammule_LINE_Color)
'prograde GraphicsWindow.SetPixel(x+iteration+1,y+PixelDraw,Flammule_LINE_Color)
'retrograde:
GraphicsWindow.SetPixel(x-iteration,y+PixelDraw,Flammule_LINE_Color)
GraphicsWindow.SetPixel(x-iteration-1,y+PixelDraw,Flammule_LINE_Color)
EndIf
EndIf
EndIf
'*============================================================
'* Two different strategies are in place regarding the persistence of flammule borders
'* (chevrons).
'* To enable the rendering of filled flammules, and to manage appropriately their
'* collisions, instead of keeping in «F» state only the upmost and downmost generators
'* of the front, all the generators in the front are kept in «F» state until the front is
'* inactivated by reaching the limiting number of fire cycles of its oldest generator.
'* As a consequence, «F» state cannot be used to discriminate the flammule borders: every
'* generator in the front is «F», both those used to draw the lateral lines and those used
'* to fill the flammule in contarsting color.
'* When choosing "collision control = OFF", the user may opt for:
'* ... disappearance of the conflicting flammule borders: the overlapping area will be
'* uniformly filled with the flammule background color
'* ... persistence of the conflicting flammule borders: even after collision, the chevrons
'* will still appear, which may lead to reticulate (criss-crossing) patterns.
'* With "collision control = OFF" and "reticulation=ON", the LastBorderState of the
'* current generator is checked. If «U» or «D» the current generator is part of the
'* chevron (flammule border)
'*============================================================
If Reticulation = "Y" Then
If LastBorderState[PixelDraw] <> "*" Then
' If the «iteration» loop has step 2, I can draw each dot twice
'prograde GraphicsWindow.SetPixel(x+iteration,y+PixelDraw,Flammule_LINE_Color)
'prograde GraphicsWindow.SetPixel(x+iteration+1,y+PixelDraw,Flammule_LINE_Color)
'retrograde:
GraphicsWindow.SetPixel(x-iteration,y+PixelDraw,Flammule_LINE_Color)
GraphicsWindow.SetPixel(x-iteration-1,y+PixelDraw,Flammule_LINE_Color)
EndIf
EndIf
EndFor
EndFor
'==============\
'===============> MAIN PROGRAM CYCLE ENDS
'==============/
'***************************************************************
'************** MULTIPLE RENDERINGS **********************
'***************************************************************
' If multiple overlapping renderings are required, I increase the
' rendering count and check it against the required number of
' renderings. A 10-point offset will be applied to each successive
' rendering, to improve the overall look
'***************************************************************
PASSES = PASSES + 1
CYCLE_OFFSET = CYCLE_OFFSET + OFFSET
If PASSES <= MAX_PASSES then
Flammule_BKG_Color = BkgColor[PASSES]
Goto OneMoreGeneration
EndIf
GraphicsWindow.ShowMessage("Rendering complete, click OK to restart","RENDERING COMPLETE!")
Reset_And_Show_Controls()
EndSub
'=====================================================
'=====================================================
' INITIALIZE GRAPHICS WINDOW CAPTIONS
'=====================================================
'=====================================================
Sub Graph_Win_Caps
GraphicsWindow.BrushColor="Red"
GraphicsWindow.FontSize = 26
GraphicsWindow.DrawText(280,5,"FLAMMULATE PATTERN GENERATOR - "+Version)
GraphicsWindow.BrushColor="Black"
GraphicsWindow.FontSize = 14
GraphicsWindow.DrawText(50,30,"CLICK BUTTONS BELOW")
GraphicsWindow.DrawText(55,45," FOR EXPLANATIONS ")
GraphicsWindow.FontSize = 14
GraphicsWindow.DrawText(275,175,"MINIMUM NUMBER OF WAIT CYCLES")
GraphicsWindow.DrawText(275,201,"MAXIMUM NUMBER OF WAIT CYCLES")
GraphicsWindow.DrawText(275,230,"MINIMUM NUMBER OF FIRE CYCLES")
GraphicsWindow.DrawText(275,256,"MAXIMUM NUMBER OF FIRE CYCLES")
GraphicsWindow.DrawText(275,290,"STEP BETWEEN ACTIVE GENERATORS")
GraphicsWindow.DrawText(275,330,"EVENNESS (E/R) + HS DELAY")
GraphicsWindow.DrawText(275,370,"BORDER LINE (Y/N)")
GraphicsWindow.DrawText(275,410,"FLAMMULE FILL (Y/N)")
GraphicsWindow.DrawText(275,450,"COLLISION CHECK (Y/N)")
GraphicsWindow.DrawText(275,490,"RETICULATION (Y/N)")
GraphicsWindow.DrawText(275,530,"UNRESPONSIVE BAND WIDTH")
GraphicsWindow.DrawText(275,570,"RANGE OF INHIBITION (2-4-8-16)")
GraphicsWindow.DrawText(275,610,"CHEVRON SURVIVAL (Y/N)")
GraphicsWindow.DrawText(275,650,"NUMBER OF RENDERINGS")
GraphicsWindow.DrawText(275,690,"OFFSET BETWEEN RENDERINGS")
GraphicsWindow.FontSize = 20
GraphicsWindow.DrawText(700,85,"AVAILABLE PRESETS")
GraphicsWindow.FontSize = 16
GraphicsWindow.DrawText(670,110,"CLICK BUTTONS HERE UNDER TO")
GraphicsWindow.DrawText(650,130,"SELECT DESCRIBE SHOW EXAMPLE")
EndSub
'=====================================================
'=====================================================
' INITIALIZE CONTROLS ( CREATE BUTTONS )
'=====================================================
'=====================================================
Sub InitControls
GraphicsWindow.BrushColor = "Green"
INPUT = Controls.AddButton("1) INPUT PARAMETERS (OR SELECT PRESET)",275, 70)
Controls.SetSize(INPUT, 300, 85)
GraphicsWindow.BrushColor = "Red"
DISCL = Controls.AddButton("DISCLAIMER & LICENSE",10, 70)
CHEVR = Controls.AddButton("THE CHEVRON PARADIGM",10, 100)
HOWTO = Controls.AddButton("HOW TO USE",10, 130)
Controls.SetSize(DISCL, 250, 25)
Controls.SetSize(CHEVR, 250, 25)
Controls.SetSize(HOWTO, 250, 25)
GraphicsWindow.BrushColor = "SlateGray"
WAITC = Controls.AddButton("Wait Cycles",10, 170)
FIREC = Controls.AddButton("Fire Cycles",10, 225)
GSTEP = Controls.AddButton("Generators Step",10, 280)
EVENR = Controls.AddButton("Even/Random Init. + HS Delay",10, 320)
BRDRL = Controls.AddButton("Border Line",10, 360)
FIFLA = Controls.AddButton("Flammule Filling",10, 400)
COLLC = Controls.AddButton("Collision Control",10, 440)
RETIC = Controls.AddButton("Reticulation",10, 480)
UNREB = Controls.AddButton("Unresponsive Band",10, 520)
RAINH = Controls.AddButton("Inhibition Range",10, 560)
CHSUR = Controls.AddButton("Chevron Survival",10, 600)
MXPSS = Controls.AddButton("N° Renderings",10, 640)
OFFRN = Controls.AddButton("Offset Rend.",10, 680)
Controls.SetSize(WAITC, 250, 50)
Controls.SetSize(FIREC, 250, 50)
Controls.SetSize(GSTEP, 250, 35)
Controls.SetSize(EVENR, 250, 35)
Controls.SetSize(BRDRL, 250, 35)
Controls.SetSize(FIFLA, 250, 35)
Controls.SetSize(COLLC, 250, 35)
Controls.SetSize(RETIC, 250, 35)
Controls.SetSize(UNREB, 250, 35)
Controls.SetSize(RAINH, 250, 35)
Controls.SetSize(CHSUR, 250, 35)
Controls.SetSize(MXPSS, 250, 35)
Controls.SetSize(OFFRN, 250, 35)
GraphicsWindow.BrushColor = "GREEN"
GraphicsWindow.FontSize = 30
GENRT = Controls.AddButton("2) GENERATE",635, 380)
Controls.SetSize(GENRT, 330, 100)
Controls.HideControl(GENRT)
GraphicsWindow.BrushColor = "Red"
CLOSE = Controls.AddButton("CLOSE PROGRAM",635, 490)
Controls.SetSize(CLOSE, 330, 140)
GraphicsWindow.BrushColor = "GREEN"
GraphicsWindow.FontSize = 16
SELCT1 = Controls.AddButton("Select 1",635, 155)
SELCT2 = Controls.AddButton("Select 2",635, 190)
SELCT3 = Controls.AddButton("Select 3",635, 225)
SELCT4 = Controls.AddButton("Select 4",635, 260)
SELCT5 = Controls.AddButton("Select 5",635, 295)
SELCT6 = Controls.AddButton("Select 6",635, 330)
Controls.SetSize(SELCT1, 80, 30)
Controls.SetSize(SELCT2, 80, 30)
Controls.SetSize(SELCT3, 80, 30)
Controls.SetSize(SELCT4, 80, 30)
Controls.SetSize(SELCT5, 80, 30)
Controls.SetSize(SELCT6, 80, 30)
DESCR1 = Controls.AddButton("Descr. 1",720, 155)
DESCR2 = Controls.AddButton("Descr. 2",720, 190)
DESCR3 = Controls.AddButton("Descr. 3",720, 225)
DESCR4 = Controls.AddButton("Descr. 4",720, 260)
DESCR5 = Controls.AddButton("Descr. 5",720, 295)
DESCR6 = Controls.AddButton("Descr. 6",720, 330)
Controls.SetSize(DESCR1, 80, 30)
Controls.SetSize(DESCR2, 80, 30)
Controls.SetSize(DESCR3, 80, 30)
Controls.SetSize(DESCR4, 80, 30)
Controls.SetSize(DESCR5, 80, 30)
Controls.SetSize(DESCR6, 80, 30)
SHOWEX1 = Controls.AddButton("SHOW EXAMPLE 1",805, 155)
SHOWEX2 = Controls.AddButton("SHOW EXAMPLE 2",805, 190)
SHOWEX3 = Controls.AddButton("SHOW EXAMPLE 3",805, 225)
SHOWEX4 = Controls.AddButton("SHOW EXAMPLE 4",805, 260)
SHOWEX5 = Controls.AddButton("SHOW EXAMPLE 5",805, 295)
SHOWEX6 = Controls.AddButton("SHOW EXAMPLE 6",805, 330)
Controls.SetSize(SHOWEX1, 160, 30)
Controls.SetSize(SHOWEX2, 160, 30)
Controls.SetSize(SHOWEX3, 160, 30)
Controls.SetSize(SHOWEX4, 160, 30)
Controls.SetSize(SHOWEX5, 160, 30)
Controls.SetSize(SHOWEX6, 160, 30)
EndSub
'=====================================================
'=====================================================
' INITIALIZE MESSAGES
'=====================================================
'=====================================================
Sub InitMessages
'--------------------------------------------------------------------------------------------------------------------------------'
' Initialize all the text variables to provide explanations:
'--------------------------------------------------------------------------------------------------------------------------------'
'--------------- Opening
Opening="This badly over-engineered piece of software failed miserably in its declared purpose - "
Opening= Opening+"delivering ornamental patterns similar to those of Oliva shells. Its main sin: taking too seriuosly the similitude between flammule and geometric triangles (there is much more...)."+CRLF
Opening= Opening+"Its only possible merit is taking to the limit the «wavefront approach» avocated, among others, by Bernard Tursch & Dietmar Greifeneder in their book «Oliva Shells - The genus Oliva and the species problem» "
Opening= Opening+"- L'Informatore Piceno (Italy), 2001. The incomparably better results provided by the software by Hans Meinhardt, «The Algorithmic Beauty of Seashells» - Springer, 1995 "
Opening= Opening+"are obtained with an entirely different approach. "+CRLF
Opening= Opening+"This program is aimed at providing a linear array of pixel generators that 'extrudes' the pattern on its entire length: "
Opening= Opening+"just in that respect, it may reflect its natural model, the shell growing edge."+CRLF
Opening= Opening+""+CRLF
Opening= Opening+" WARNING !!! "+CRLF
Opening= Opening+""+CRLF
Opening= Opening+"While taking advantage of some of the best virtues of Small Basic, this program takes also its worst defect - slowness. The generation of a whole screen may take several minutes."
'--------------- Disclaimer & License
Disclaimer="This software is not designed to generate pixel-perfect nor life-like renditions of the "
Disclaimer= Disclaimer+"ornamental patterns of seashells, but rather to elucidate algorithmically the mechanism underlying the generation of chevron patterns and flammules."+CRLF
Disclaimer= Disclaimer+"The design was inspired by books including: Bernard Tursch & Dietmar Greifeneder, «Oliva Shells - The genus Oliva and the species problem» "+CRLF
Disclaimer= Disclaimer+"- L'Informatore Piceno (Italy), 2001 and Hans Meinhardt, «The Algorithmic Beauty of Seashells» - Springer, 1995"+CRLF
Disclaimer= Disclaimer+"The Microsoft Small Basic source code is provided for anybody to try and enhance the current release. "
Disclaimer= Disclaimer+"Compromises accepted to limit the complexity of software developement include the following:"+CRLF
Disclaimer= Disclaimer+" - especially when collision control is inactivated, intersecting flammules, particularly "
Disclaimer= Disclaimer+"in regular patterns, may show a small constriction whenever a flammule is pinched "
Disclaimer= Disclaimer+"between similar elements."+CRLF
Disclaimer= Disclaimer+"The interventions needed to minimize that effect, would "
Disclaimer= Disclaimer+"in turn disrupt the efficacy of collision control. "+CRLF
Disclaimer= Disclaimer+"A major software re-engineering would be needed to overcome the undesired effects "
Disclaimer= Disclaimer+"of such compromises."+CRLF
Disclaimer= Disclaimer+"The software is provided under MIT License."+CRLF
Disclaimer= Disclaimer+"THE SOFTWARE IS PROVIDED "+Text.GetCharacter(34)+"AS IS"+Text.GetCharacter(34)+", WITHOUT WARRANTY OF "
Disclaimer= Disclaimer+"ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS "
Disclaimer= Disclaimer+"FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE "
Disclaimer= Disclaimer+"LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
Disclaimer= Disclaimer+"ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
'--------------- The Chevron Paradigm
Paradigm = "Patterns are generated by a 500px linear, vertical «Generator array», working cyclically in a fashion similar"
Paradigm = Paradigm + "to a loom: the pattern unfolds one line per program cycle, and the line shows one point for each ON Generator."
Paradigm = Paradigm + "This setup is a simplification of Meinhardt's reaction-diffusion model and of the chevron paradigm as described"
Paradigm = Paradigm + "by Tursch & Greifeneder. The setup is meant to approximate the growing edge of the living animal."+CRLF
Paradigm = Paradigm + "Starting from each ON Generator, Activation propagates up and down the array in «activation cascades» that"
Paradigm = Paradigm + "may be described as «activation waves». "+CRLF+CRLF
Paradigm = Paradigm + "Generators cycle through the 2 states described below: each state"
Paradigm = Paradigm + "is assigned its LATENCY - a number of inactive cycles after which the state changes."+CRLF
Paradigm = Paradigm + " «W» (WAIT) - the waiting Generator hasn't enough charge to FIRE on his own, but can propagate activation waves, "
Paradigm = Paradigm + "in other words, can change to state «F» as soon as it intercepts an «activation wave». Unless the "
Paradigm = Paradigm + "Generator is activated by oncoming waves, latency count is increased until the required number of "
Paradigm = Paradigm + "WAIT cycles is reached then, at the next cycle, the Generator will enter state «F»;"+CRLF
Paradigm = Paradigm + " «F» (FIRE) - the charged Generator FIRES on his own, and generates an an «activation wave» that involves both "
Paradigm = Paradigm + "the adjacent generators (above and below). Unless inactivated by COLLISION, latency count is "
Paradigm = Paradigm + "increased until the required number of FIRE cycles is reached then, at the next cycle, the Generator "
Paradigm = Paradigm + "will enter state «W» - at the same time, the whole propagation front (see below) is reset;"+CRLF
Paradigm = Paradigm + "The term «spontaneous activation» refers to the «W»/«F» transition."+CRLF+CRLF
Paradigm = Paradigm + "When two activations waves collide, in other words, when a Generator in state «F» is detected in proximity of the"
Paradigm = Paradigm + "current sensor also in state «F», all the sensors in the propagation front (group of adjacent sensors in state «F»)"
Paradigm = Paradigm + "are reset to «W» (a situation that generates a «flammule base».)"+CRLF
Paradigm = Paradigm + "The propagation is inactivated in exactly the same way, whenever the required fire cycles of its originating generator expire."+CRLF
Paradigm = Paradigm + "The states and events described above result in triangular elements ("+Text.GetCharacter(34)+"FLAMMULES"+Text.GetCharacter(34)+")"
Paradigm = Paradigm + Text.GetCharacter(34)+" arranged in more or less regular patterns."
'--------------- General Explanations (HOW TO USE)
Explanations = "User will start by providing the parameters governing the generation of a pattern, pressing one "
Explanations = Explanations +"of the two buttons marked with «1)», thus choosing between:"+CRLF
Explanations = Explanations +" - Typing the needed values in a text box, or... "+CRLF
Explanations = Explanations +" - Choosing preset values from a few alternative setups."+CRLF
Explanations = Explanations +"As soon as valid values are provided, the button «2 - GENERATE» can be clicked."+CRLF
Explanations = Explanations +"Parameters allow the user toopt for a fully supervised simulation, in which no kind of randomization occurs and the latency of "
Explanations = Explanations +"each state is fixed at its MINIMUM LATENCY value. Otherwise, each Generator is assigned random latency for wait "
Explanations = Explanations +"and fire, by random extraction of a value between the MINIMUM and MAXIMUM LATENCY values input by user (MAXIMUM "
Explanations = Explanations +"must not be lower than the corresponding MINIMUM value)."+CRLF
Explanations = Explanations +"The program enforces limits for input values values, chosen for a clearer depiction of the patterns. "
Explanations = Explanations +"A separate button provides more detailed explanations for each kind of parameter."
'--------------- Wait Cycles
Expl_WAIT = "Generators at the growth edge do not fire continuously: they need a «W» (wait) period to recharge."+CRLF
Expl_WAIT = Expl_WAIT + "Depending from the number of cycles spent in state «W», activations will be more or less frequent."+CRLF
Expl_WAIT = Expl_WAIT + "User is required to input a MINIMUM and a MAXIMUM number of wait cycles."+CRLF
Expl_WAIT = Expl_WAIT + "If SUPERVISED (non-randomic) settings are chosen, each Generator will be assigned the MINMUM number of wait cycles, "
Expl_WAIT = Expl_WAIT + "otherwise each Generator will be assigned a random number of wait cycles, between the minimum and the maximum value."
'--------------- Fire Cycles
Expl_FIRE = "After entering the «F» state, the Generator does not keep on firing indefinitely: it will stop firing end re-enter «W» state after a given number of cycles."+CRLF
Expl_FIRE = Expl_FIRE + "Depending from the number of cycles spent in state «F», flammules may be longer or shorter."+CRLF
Expl_FIRE = Expl_FIRE + "User is required to input a MINIMUM and a MAXIMUM number of fire cycles."+CRLF
Expl_FIRE = Expl_FIRE + "If SUPERVISED (non-randomic) settings are chosen, each Generator will be assigned the MINMUM number of fire cycles, "
Expl_FIRE = Expl_FIRE + "otherwise each Generator will be assigned a random number of fire cycles, between the minimum and the maximum value."
'--------------- Step
Expl_STEP = "To enable the generation of a realistic pattern, active Generators need to be more or less spaced along the the array: the lower the step, "
Expl_STEP = Expl_STEP + "the finer the pattern that will be generated (depending also on wait cycles)."+CRLF
Expl_STEP = Expl_STEP + "User is required to input a value for the STEP parameter."+CRLF
Expl_STEP = Expl_STEP + "If SUPERVISED (non-randomic) settings are chosen, for the initial iterations a Generator will be positioned exactly at each step and half-step, "
Expl_STEP = Expl_STEP + "otherwise a Generator will be positioned approximately (with a randomic offset up to 15% of the step)."
'--------------- Supervised
Expl_SUPERVISED = "EVEN (SUPERVISED) OR RANDOM INITIALIZATION"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "User can opt for non-randomic («SUPERVISED») or randomic initialization."+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "The RANDOM scenario will include..."+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... Random initial position of some «F» Generators (roughly positioned at a more or less fixed step),"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... Random required wait cycles (between minimum and maximum value input by user),"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... Random required fire cycles (between minimum and maximum value input by user),"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... spontaneous activation enabled for all the Generators,"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "The SUPERVISED scenario will include..."+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... Fixed state of the Generators = «W» (Wait),"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... Fixed initial position of some «F» Generators (exactly positioned at a fixed step),"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... Fixed initial wait cycles of those Generators = minimum value input by user, thus "
Expl_SUPERVISED = Expl_SUPERVISED + "allowing a simultaneous activation of the Generators,"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... Fixed required wait cycles = minimum value input by user,"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... Fixed required fire cycles = minimum value input by user,"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "... spontaneous activation enabled only for the regularly spaced, initial generators"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "HALF STEP (HS) DELAY"+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "In supervised renderings, half of the generators are immediately active and, at each half-step, a generator "
Expl_SUPERVISED = Expl_SUPERVISED + "in state «W» is placed, so that a more interesting pattern is generated."+CRLF
Expl_SUPERVISED = Expl_SUPERVISED + "User can opt for an immediate activation of all the generators, that will all start simultaneously."+CRLF
'--------------- Border
Expl_BORDER = "The user will be asked whether, whenever propagation is interrupted, a continuous line should mark the inactivated front. "
Expl_BORDER = Expl_BORDER + "If affirmative..."+CRLF
Expl_BORDER = Expl_BORDER + "... the whole perimetre of each flammule will be marked by a contrasting line,"+CRLF
Expl_BORDER = Expl_BORDER + " if negative..."+CRLF
Expl_BORDER = Expl_BORDER + "... the contrasting line will mark just the sides of the flammule ( = the chevron)."+CRLF
'--------------- Flammule Filling
Expl_FIFLA = "The flammules may be filled with a contrasting background, as usually observed in actual ornamentation. If filled flammules are chosen..."+CRLF
Expl_FIFLA = Expl_FIFLA + "... the area inside the flammule will be colored,"+CRLF
Expl_FIFLA = Expl_FIFLA + "Otherwise..."+CRLF
Expl_FIFLA = Expl_FIFLA + "... the area inside the flammule will be filled with the background color."+CRLF
'--------------- Collision
Expl_COLLISION = "According to the Gierer-Meinhardt model, converging activation waves are subjected "
Expl_COLLISION = Expl_COLLISION + "to mutual elision. Apart from exhaustion of «F» cycles, mutual elision on collision "
Expl_COLLISION = Expl_COLLISION + "is an easily observed phenomenon in shell ornamentation."+CRLF
Expl_COLLISION = Expl_COLLISION + "Collision control generates well-separated flammules, by inhibiting overlapping."+CRLF
Expl_COLLISION = Expl_COLLISION + "If collision control is enabled..."+CRLF
Expl_COLLISION = Expl_COLLISION + "... flammules will not overlap,"+CRLF
Expl_COLLISION = Expl_COLLISION + "if disabled..."+CRLF
Expl_COLLISION = Expl_COLLISION + "... the generation of flammules will be stopped only when required FIRE cycles are reached. "
Expl_COLLISION = Expl_COLLISION + "As a consequence, flammules may overlap and coalesce in blotches or bands."+CRLF
'--------------- Reticulation
Expl_RETIC = "If collision control is OFF, the encounter of activation waves may be managed in two ways:"+CRLF
Expl_RETIC = Expl_RETIC + "if RETICULATION is enabled, ..."+CRLF
Expl_RETIC = Expl_RETIC + "... the chevron lines (lateral borders of the flammule) continue to be visible until limit number of fire cycles is reached "
Expl_RETIC = Expl_RETIC + "thus generating a criss-cross or reticulate pattern."+CRLF
Expl_RETIC = Expl_RETIC + "if RETICULATION is disabled, ..."+CRLF
Expl_RETIC = Expl_RETIC + "... the chevron lines (lateral borders of the flammule) disappear after the collision."+CRLF
'--------------- Unresponsive Band
Expl_UNRESPONSIVE = "User can choose whether the rendering should include an UNRESPONSIVE BAND at the center of the rendering, "
Expl_UNRESPONSIVE = Expl_UNRESPONSIVE + "to simulate an often-observed feature appearing whenever a set of contiguous "
Expl_UNRESPONSIVE = Expl_UNRESPONSIVE + "permanently activated or permanently inactive generators affect the pattern with an even band "
Expl_UNRESPONSIVE = Expl_UNRESPONSIVE + "of contrasting color."+CRLF
Expl_UNRESPONSIVE = Expl_UNRESPONSIVE + "The Generators in the unresponsive band..."+CRLF
Expl_UNRESPONSIVE = Expl_UNRESPONSIVE + "... will never activate,"+CRLF
Expl_UNRESPONSIVE = Expl_UNRESPONSIVE + "... will appear as a grey line in the rendering."+CRLF
Expl_UNRESPONSIVE = Expl_UNRESPONSIVE + "The UNRESPONSIVE BAND will appear horizontally at the center of the rendering."+CRLF
'--------------- Inhibition Range
Expl_RAINH = "To provide a more realistic rendering, spontaneous activation cannot occur in the immediate vicinities "
Expl_RAINH = Expl_RAINH + "of a propagating generator. User can opt for one of four diameters of the «range of inhibition»:" +CRLF
Expl_RAINH = Expl_RAINH + "2, 4, 8 or 16 positions."+CRLF
Expl_RAINH = Expl_RAINH + "Ranges higher than 2 will progressively obliterate the smallest flammules."+CRLF
'--------------- Chevron survival
Expl_CHSUR = "Usually, as soon as the number of fire cycles of a propagation front expires, both the flammula and the chevron, "
Expl_CHSUR = Expl_CHSUR + "including reticulation, are truncated. User can opt for a «chevron survive the propagation front» option."+CRLF
Expl_CHSUR = Expl_CHSUR + " If affirmative..." +CRLF
Expl_CHSUR = Expl_CHSUR + "... the reticulation will continue even after expiration of a propagation wave."+CRLF
Expl_CHSUR = Expl_CHSUR + "Otherwise..."+CRLF
Expl_CHSUR = Expl_CHSUR + "... as soon as a propagation front expires, both its side lines, and any line overlapping the flammule, will be truncated."+CRLF
Expl_CHSUR = Expl_CHSUR + "Note: if COLLISION CHECK is ON, the only surviving chevrons will be the ones from the fronts undergoing spontaneous inactivation "
Expl_CHSUR = Expl_CHSUR + "after reaching their expected fire cycles."
'--------------- Number of Renderings
Expl_MXPSS = "User can decide to execute more than one (up to ten) full image generation cycles."+CRLF
Expl_MXPSS = Expl_MXPSS + "If more than one cycle is chosen..."+CRLF
Expl_MXPSS = Expl_MXPSS + "... once the first full rendering is complete, another rendering will begin, overlaid above the previous rendering," +CRLF
Expl_MXPSS = Expl_MXPSS + "... successive rendering will be slightly offset to the right, to generate more complex patterns."
'--------------- Offset among Renderings
Expl_OFFRN = "User can decide to execute more than one (up to four) full image generation cycles."+CRLF
Expl_OFFRN = Expl_OFFRN + "If more than one cycle is chosen, an offset in pixel between successive renderings should be specified (e.g. 30 or 60 pixel)."
EndSub
'=====================================================
'=====================================================
' LOAD IMAGE SAMPLES
'=====================================================
'=====================================================
Sub Load_Image_Samples
CurrDir=Program.Directory
ImageName1 = ImageList.LoadImage(Currdir+"\Example_1.png")
ImageName2 = ImageList.LoadImage(Currdir+"\Example_2.png")
ImageName3 = ImageList.LoadImage(Currdir+"\Example_3.png")
ImageName4 = ImageList.LoadImage(Currdir+"\Example_4.png")
ImageName5 = ImageList.LoadImage(Currdir+"\Example_5.png")
ImageName6 = ImageList.LoadImage(Currdir+"\Example_6.png")
Name_Example[1] = "TRIPLE PASS, COLLISION CONTROL ON, MEDIUM SIZE, INH8"
Descr_Example[1] = "Three Renderings, Random, Full Perimeter, Medium Size Filled Flammules, "
Descr_Example[1] = Descr_Example[1] + "Inhibition at 8 step away, Collision Check ON"
Name_Example[2] = "EMERGING STABLE RETICULATION (FINE MESH)"
Descr_Example[2] = "One Rendering, Supervised, Chevrons Only (Open Flammules), No Fill, Reticulation Enabled, "
Descr_Example[2] = Descr_Example[2] + "Chevron Survival ON, Collision check OFF"
Name_Example[3] = "OPEN FLAMMULES, NO FILL, MEDIUM COLLISION RATE"
Descr_Example[3] = "One Rendering, Random, Chevrons Only (Open Flammules), No Fill, Reticulation Disabled, "
Descr_Example[3] = Descr_Example[3] + "Collision check ON"
Name_Example[4] = "COALESCENT BANDS, HIGH COLLISION RATE, COLLISION CONTROL OFF"
Descr_Example[4] = "One Rendering, Random, Small Filled Flammules, Collision Check OFF, Reticulation "
Descr_Example[4] = Descr_Example[4] + "Disabled, Coalescent Bands Emerging"
Name_Example[5] = "RETICULATE AND COALESCENT BANDS, MEDIUM COLLISION RATE, COLLISION CONTROL OFF"
Descr_Example[5] = "One Rendering, Random, Medium Filled Flammules, Collision Check OFF, Reticulation "
Descr_Example[5] = Descr_Example[5] + "Enabled, Reticulate Coalescent Bands Emerging"
Name_Example[6] = "SUPERVISED, COLLIDING, COLLISION CONTROL OFF"
Descr_Example[6] = "One Rendering, Supervised, Filled Flammules, Collision Check OFF, Reticulation "
Descr_Example[6] = Descr_Example[6] + "Disabled, Regular Pattern Emerging"
'===================================================================
' THE DETAILED PARAMETERS ASSOCIATED WITH EACH EXAMPLE SETUP ARE SET
' BY THE CHOOSE_PRESET() SUBROUTINE. IF NEW EXAMPLES ARE INCLUDED, ALSO
' THE SUBROUTINE WILL NEED TO BE UPDATED ACCORDINGLY!
'===================================================================
EndSub
'=========================
'=========================
' MANAGE_RETICULATION
'=========================
'=========================
Sub Manage_Reticulation
'============================================
'============================================
'============================================
' RETICULATION(=VISUALIZATION OF CHEVRON
' LINES) CONTROL
'============================================
' U = propagating UP
' D = propagating DOWN
' B = Propagating BOTH WAYS
'============================================
'(LastBorderState is used to provide reticulate patterns)
'What happens when a collision takes place?
'Collision may be diagnosed by finding LastBorderState «U»
' BELOW LastBorderState «D» (or vice versa). In that
' case, current generator should take the LastBorderState of
' the adjacent generator
'============================================
' CHEVRON PROPAGATION MAY OCCUR UNDER TWO
' CONDITIONS:
' ... WHEN STATE = «F»
' ... REGARDLESS OF THE STATE, WHEN CHEVSURV = "Y"
' (meaning: chevron survives even after the inactivation of
' the propagation front)
'============================================
If curr_prop_stat[This_Generator] = "A" Then
NextBorderState[This_Generator] = "*"
Else
' Just one of the two condition suffices!
If curr_prop_stat[This_Generator] = "F" or ChevSurv = "Y" Then
If LastBorderState[This_Generator] = "D" Or LastBorderState[This_Generator] = "B" Then
'============================================
'This may be a border (chevron) Line propagating DOWN
'(see explanations above)
'============================================
If DEBUG Then '-> DEBUG
TextWindow.CursorTop = 0 '-> DEBUG
TextWindow.CursorLeft = 29 '-> DEBUG
TextWindow.Write("PROPAGATION DOWN - LastBorderState - 1 " + LastBorderState[This_Generator-1]) '-> DEBUG
TextWindow.Write(" - LastBorderState " + LastBorderState[This_Generator]) '-> DEBUG
TextWindow.Write(" - LastBorderState + 1 " + LastBorderState[This_Generator+1]) '-> DEBUG
'TextWindow.Read() '-> DEBUG
EndIf
'=========> One, or both, adjacent generators are MAYBE colliding
'=========> Current propagation DOWN - Adjacent generator NOT colliding when...
'=========> - LastBorderState[This_Generator-1] = "D" = parallel propagation D above
'=========> - LastBorderState[This_Generator-1] = "U" = DIVERGING propagation U above
'=========> - LastBorderState[This_Generator+1] = "D" = parallel propagation D below
'=========> Adjacent generators COLLIDING when...
'=========> - LastBorderState[This_Generator+1] = "U" = CONVERGING propagation U below
If LastBorderState[This_Generator+1] = "*" Then
'=========> No collision BELOW! Keep propagating DOWN!
NextBorderState[This_Generator] = "*"
'------------Check NEXT state BELOW
If NextBorderState [This_Generator+1] = "*" Then
'---------NEXT STATE BELOW free - Set to "D"
NextBorderState[This_Generator+1] = "D"
Else
'HERE WHEN attempting to overwrite NEXT STATE BELOW
If NextBorderState[This_Generator+1] = "U" Then
'if NEXT STATE BELOW = "U", reset so it will propagate both ways!
NextBorderState[This_Generator+1] = "B"
EndIf
EndIf
Else
'---------------------------------------------------------------------------------------
'==> Here when BELOW the current generator "U", "D" or "B" are found
'---------------------------------------------------------------------------------------
If LastBorderState[This_Generator+1] = "U" Then
'The generator BELOW is propagating UP! SWAP PROPAGATION!
NextBorderState[This_Generator] = "U"
NextBorderState[This_Generator+1] = "D"
Else
'If another "D" or "B" can be found under the current generator, they
'will be managed at the next cycle of the loop
Nothing()
EndIf
EndIf 'END IF LastBorderState[This_Generator+1] = "*"
EndIf 'END IF LastBorderState[This_Generator] = "D" Or LastBorderState[This_Generator] = "B"
If LastBorderState[This_Generator] = "U" Or LastBorderState[This_Generator] = "B" Then
'============================================
'This may be a border (chevron) Line propagating UP
'(see explanations above)
'============================================
If DEBUG Then '-> DEBUG
TextWindow.CursorTop = 0 '-> DEBUG
TextWindow.CursorLeft = 29 '-> DEBUG
TextWindow.Write("PROPAGATION UP - LastBorderState - 1 " + LastBorderState[This_Generator-1]) '-> DEBUG
TextWindow.Write(" - LastBorderState " + LastBorderState[This_Generator]) '-> DEBUG
TextWindow.Write(" - LastBorderState + 1 " + LastBorderState[This_Generator+1]) '-> DEBUG
'TextWindow.Read() '-> DEBUG
EndIf
'=========> One, or both, adjacent generators are MAYBE colliding
'=========> Current propagation UP - Adjacent generator NOT colliding when...
'=========> - LastBorderState[This_Generator+1] = "U" = parallel propagation U below
'=========> - LastBorderState[This_Generator+1] = "D" = DIVERGING propagation D below
'=========> - LastBorderState[This_Generator-1] = "U" = parallel propagation U above
'=========> Adjacent generators COLLIDING when...
'=========> - LastBorderState[This_Generator-1] = "D" = CONVERGING propagation D above
If LastBorderState[This_Generator-1] = "*" Then
'=========> No collision ABOVE! Keep propagating UP!
NextBorderState[This_Generator] = "*"
'------------Check NEXT state ABOVE
If NextBorderState [This_Generator-1] = "*" Then
'---------NEXT STATE ABOVE free - Set to "U"
NextBorderState[This_Generator-1] = "U"
Else
'HERE WHEN attempting to overwrite NEXT STATE ABOVE
If NextBorderState[This_Generator-1] = "D" Then
'if NEXT STATE ABOVE = "D", reset so it will propagate both ways!
NextBorderState[This_Generator-1] = "B"
EndIf
EndIf
Else
'---------------------------------------------------------------------------------------
'==> Here when ABOVE the current generator "U", "D" or "B" are found
'---------------------------------------------------------------------------------------
If LastBorderState[This_Generator-1] = "D" Then
'The generator ABOVE is propagating DOWN! SWAP PROPAGATION!
NextBorderState[This_Generator-1] = "U"
NextBorderState[This_Generator] = "D"
Else
'If another "U" or "B" can be found under the current generator, they
'will be managed at the next cycle of the loop
Nothing()
EndIf
EndIf 'END IF LastBorderState[This_Generator-1] = "*"
EndIf 'END IF LastBorderState[This_Generator] = "U" Or LastBorderState[This_Generator] = "B"
EndIf ' END IF curr_prop_stat[This_Generator] = "F" or ChevSurv = "Y"
EndIf ' END IF curr_prop_stat[This_Generator] = "A"
EndSub
'=========================
'=========================
' MESSAGE_0_0_AND_WAIT
'=========================
'=========================
Sub MESSAGE_0_0_AND_WAIT
TextWindow.CursorTop = 0
TextWindow.CursorLeft = 0
TextWindow.Write(" ")
TextWindow.CursorTop = 0
TextWindow.CursorLeft = 0
TextWindow.Write(Message_00)
If Waitkey = "True" Then
TextWindow.Read()
EndIf
EndSub
'=========================
'=========================
' NOTHING
'=========================
'=========================
Sub Nothing
'============================================================
'Pseudo-Subroutine that allows the use of Nothing() as
'as a statement
'============================================================
EndSub
'=====================================================
'=====================================================
' ON BUTTON CLICK
'=====================================================
'=====================================================
Sub OnButtonClick
Button = Controls.LastClickedButton ' Last selected button name
ButtonCap = Controls.GetButtonCaption(Button) ' Its corresponding caption
EndSub
'=====================================================
'=====================================================
' INITIALIZE AND DISPLAY EMPTY PARAMETERS
'=====================================================
'=====================================================
Sub Parameters_Initialize
Min_Wait_Cycles = 0
Max_Wait_Cycles = 0
Min_Fire_Cycles = 0
Max_Fire_Cycles = 0
Step_Size_Px = 0
Evenness = " "
HALFSTEP_DELAY = " "
Mark_Inact_Front = " "
Collision_Check = " "
Unresponsive_Band = 0
FillFlam = " "
Reticulation = " "
RANGE_INHIB = 0
ChevSurv = " "
MAX_PASSES = 0
'===================> Graphics Window is not self-clearing
'===================> new values will be overwritten above
'===================> existing values, unless cleared
GraphicsWindow.BrushColor=GraphicsWindow.BackgroundColor
GraphicsWindow.FillRectangle(538,170, 25, 500)
GraphicsWindow.BrushColor="Green"
GraphicsWindow.FontSize = 16
GraphicsWindow.DrawText(540,175, Min_Wait_Cycles)
GraphicsWindow.DrawText(540,201, Max_Wait_Cycles)
GraphicsWindow.DrawText(540,230, Min_Fire_Cycles)
GraphicsWindow.DrawText(540,256, Max_Fire_Cycles)
GraphicsWindow.DrawText(540,290, Step_Size_Px)
GraphicsWindow.DrawText(540,330, Evenness)
GraphicsWindow.DrawText(555,330, HALFSTEP_DELAY)
GraphicsWindow.DrawText(540,370, Mark_Inact_Front)
GraphicsWindow.DrawText(540,410, FillFlam)
GraphicsWindow.DrawText(540,450, Collision_Check)
GraphicsWindow.DrawText(540,490, Reticulation)
GraphicsWindow.DrawText(540,530, Unresponsive_Band)
GraphicsWindow.DrawText(540,570, RANGE_INHIB)
GraphicsWindow.DrawText(540,610, ChevSurv)
GraphicsWindow.DrawText(540,650, MAX_PASSES)
EndSub
'=========================
'=========================
' PROPAGATE_F_STATE
'=========================
'=========================
Sub Propagate_F_STATE
'==============================
' Propagate wave FORWARD
'==============================
If next_prop_stat[WhichGen] <> "F" then
WhichColor[WhichGen] = Flammule_LINE_Color
EndIf
next_prop_stat[WhichGen] = "F"
'the Generator will keep the Activation Code of its propagation front
'ActCode[WhichGen] that was set at first activation of the generator
'the Generator will keep the OP_ITERATION number of the initiation
'of the propagation front (defined by the first generator of the front)
'Cycle_Activated[WhichGen] was set at first activation of the generator
'--> As soon as a Generator enters state «F», it is assigned the same
'--> Last_Fire_Cycle as its promoter. This is not needed for
'--> current generator (forward propagation) that was already
'--> in state «F»
'Monitor_Fire_Expired is the number of the Generator that initiated a propagation
'front. All the Generators in the front will monitor the expiration of fire cycles of their
'initial promoter. This is not needed for current generator, that was already in state «F»
'==============================
'==============================
'==============================
' Propagate wave UP
'==============================
'==============================
'==============================
'If the Generator above allows propagation...
' STATE «W» allows propagation
' Legitimately, a previous «F» propagation may have set
' a generator above me in «F» state - in that case i should do nothing
'- propagate up
If next_prop_stat[WhichGen-1] = "W" Then
WhichColor[WhichGen] = Flammule_LINE_Color
'the Generator above will propagate the «F» wave
next_prop_stat[WhichGen-1] = "F"
'--> As soon as a Generator enters state «F», its
'--> Cur_Wait_Cycles are zeroed
Cur_Wait_Cycles[WhichGen-1] = 0
'the Generator above will inherit the Activation Code of its
'propagation front (defined by the first generator of the front)
ActCode[WhichGen-1] = ActCode[WhichGen]
'the Generator above will inherit the OP_ITERATION number of the initiation
'of the propagation front (defined by the first generator of the front)
Cycle_Activated[WhichGen-1] = Cycle_Activated[WhichGen]
'--> As soon as a Generator enters state «F», it is assigned the same
'--> Last_Fire_Cycle as its promoter.
Last_Fire_Cycle[WhichGen-1] = Last_Fire_Cycle[WhichGen]
'Monitor_Fire_Expired is the number of the Generator that initiated a propagation
'front. All the Generators in the front will monitor the expiration of fire cycles of their
'initial promoter.
Monitor_Fire_Expired[WhichGen-1] = Monitor_Fire_Expired[WhichGen]
'Otherwise...
Else
'------------------------> DEBUG start
If DEBUG And WhichGen < 76 Then '-> DEBUG
TextWindow.CursorTop = 0 '-> DEBUG
TextWindow.CursorLeft = 29 '-> DEBUG
TextWindow.Write("Line 1750 - Generator above is " + next_prop_stat[WhichGen-1]+"! ") '-> DEBUG
TextWindow.Write("Can't propagate UP!") '-> DEBUG
'TextWindow.Read() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG end
EndIf ' END IF next_prop_stat [WhichGen-1] = "W"
'==============================
'==============================
'==============================
' Propagate wave DOWN
'==============================
'==============================
'==============================
'If the Generator below allows propagation...
' STATE «W» allows propagation
' Legitimately, a previous «F» propagation may have set
' a generator above me in «F» state - in that case i should do nothing
'- propagate down
If next_prop_stat[WhichGen+1] = "W" Then
WhichColor[WhichGen] = Flammule_LINE_Color
'the Generator below will propagate the «F» wave
next_prop_stat[WhichGen+1] = "F"
'--> As soon as a Generator enters state «F», its
'--> Cur_Wait_Cycles are zeroed
Cur_Wait_Cycles[WhichGen+1] = 0
'the Generator below will inherit the Activation Code of its
'propagation front (defined by the first generator of the front)
ActCode[WhichGen+1] = ActCode[WhichGen]
'the Generator below will inherit the OP_ITERATION number of the initiation
'of the propagation front (defined by the first generator of the front)
Cycle_Activated[WhichGen+1] = Cycle_Activated[WhichGen]
'--> As soon as a Generator enters state «F», it is assigned the same
'--> Last_Fire_Cycle as its promoter.
Last_Fire_Cycle[WhichGen+1] = Last_Fire_Cycle[WhichGen]
'Monitor_Fire_Expired is the number of the Generator that initiated a propagation
'front. All the Generators in the front will monitor the expiration of fire cycles of their
'initial promoter.
Monitor_Fire_Expired[WhichGen+1] = Monitor_Fire_Expired[WhichGen]
'Otherwise...
Else
'------------------------> DEBUG start
If DEBUG And WhichGen < 76 Then '-> DEBUG
TextWindow.CursorTop = 0 '-> DEBUG
TextWindow.CursorLeft = 29 '-> DEBUG
TextWindow.Write("Line 1790 Generator below is " + next_prop_stat[WhichGen+1]+"! ") '-> DEBUG
TextWindow.Write("Can't propagate DOWN!") '-> DEBUG
'TextWindow.Read() '-> DEBUG
EndIf '-> DEBUG
'------------------------> DEBUG end
EndIf ' END IF next_prop_stat [WhichGen+1] = "W"
EndSub
'========================= ==
'===========================
' RANDOMIZE_LAST_WAIT_CYCLE
'===========================
'===========================
Sub Randomize_Last_Wait_Cycle
'================================================================
'LAST WAIT CYCLES is initialized at OP_ITERATION 1 with a random value
'in three ranges
' - between 1 and 20% the required WAIT of Generator "WhichGen"
' - between 40% and 60% the required WAIT of Generator "WhichGen"
' - between 60% and 80% the required WAIT of Generator "WhichGen"
'Ranges cycle in the order short - medium - long - medium - short - medium - long ......
'================================================================
If Initial_Wait = "SHORT" Then
Initial_Wait = "MEDIUM_U"
Low_Range = 1
High_Range = math.Round(Required_Wait_Cycles[WhichGen]*0.2)
EndIf
If Initial_Wait = "MEDIUM_U" Then
Initial_Wait = "LONG"
Low_Range = math.Round(Required_Wait_Cycles[WhichGen]*0.4)
High_Range = math.Round(Required_Wait_Cycles[WhichGen]*0.6)
EndIf
If Initial_Wait = "LONG" Then
Initial_Wait = "MEDIUM_D"
Low_Range = math.Round(Required_Wait_Cycles[WhichGen]*0.6)
High_Range = math.Round(Required_Wait_Cycles[WhichGen]*0.8)
EndIf
If Initial_Wait = "MEDIUM_D" Then
Initial_Wait = "SHORT"
Low_Range = math.Round(Required_Wait_Cycles[WhichGen]*0.4)
High_Range = math.Round(Required_Wait_Cycles[WhichGen]*0.6)
EndIf
RETRY_CUR_WAIT_CYCLES:
CurWaitCyclesThisGen = Math.GetRandomNumber(High_Range)
If CurWaitCyclesThisGen < Math.GetRandomNumber(Low_Range) Then
Goto RETRY_CUR_WAIT_CYCLES
EndIf
Last_Wait_Cycle[WhichGen] = CurWaitCyclesThisGen
EndSub
'=====================================================
'=====================================================
' RESET GRAPHICS WINDOW AND SHOW CONTROLS
'=====================================================
'=====================================================
Sub Reset_And_Show_Controls
GraphicsWindow.BrushColor=GraphicsWindow.BackgroundColor
GraphicsWindow.FillRectangle(0,0,1400,800)
Controls.ShowControl(DISCL)
Controls.ShowControl(CHEVR)
Controls.ShowControl(HOWTO)
Controls.ShowControl(WAITC)
Controls.ShowControl(FIREC)
Controls.ShowControl(GSTEP)
Controls.ShowControl(EVENR)
Controls.ShowControl(BRDRL)
Controls.ShowControl(FIFLA)
Controls.ShowControl(COLLC)
Controls.ShowControl(RETIC)
Controls.ShowControl(UNREB)
Controls.ShowControl(RAINH)
Controls.ShowControl(CHSUR)
Controls.ShowControl(MXPSS)
Controls.ShowControl(OFFRN)
Controls.ShowControl(INPUT)
Controls.ShowControl(CLOSE)
Controls.ShowControl(SELCT1)
Controls.ShowControl(SELCT2)
Controls.ShowControl(SELCT3)
Controls.ShowControl(SELCT4)
Controls.ShowControl(SELCT5)
Controls.ShowControl(SELCT6)
Controls.ShowControl(DESCR1)
Controls.ShowControl(DESCR2)
Controls.ShowControl(DESCR3)
Controls.ShowControl(DESCR4)
Controls.ShowControl(DESCR5)
Controls.ShowControl(DESCR6)
Controls.ShowControl(SHOWEX1)
Controls.ShowControl(SHOWEX2)
Controls.ShowControl(SHOWEX3)
Controls.ShowControl(SHOWEX4)
Controls.ShowControl(SHOWEX5)
Controls.ShowControl(SHOWEX6)
'GENRT will remain hidden until new parameters are set
'--------------------------------------------------------------------------------------------------------------------------------'
' Graphic Windows Caption Initialization:
'--------------------------------------------------------------------------------------------------------------------------------'
Graph_Win_Caps()
EndSub
'=========================
'=========================
' RESET_NEXT_GEN_STATE
'=========================
'=========================
Sub Reset_Next_Gen_State
'==============================================
' RESET NEXT STATE of Generator WhichGen
'==============================================
'When resetting the topmost generator in a front, I should verify
'whether the NEXT GEN STATE of the current generator was
'legitimately set to "F" by a propagating front ABOVE.
' Unless the «W» is irreversible (as in the minimal randomization scenario)
' - PROPAGATION STRATEGY next_prop_stat[] to «W»
' - CURRENT WAIT CYCLES Cur_Wait_Cycles to 0
' - REQUIRED WAIT CYCLES Required_Wait_Cycles to new randomized value
' (unless opted for fixed value)
' - CURRENT FIRE CYCLES Cur_Fire_Cycles to 0
' - REQUIRED FIRE CYCLES Required_Wait_Cycles to new randomized value
' (unless opted for fixed value)
If curr_prop_stat[WhichGen] <> "A" Then
next_prop_stat[WhichGen] = "W"
Cur_Wait_Cycles[WhichGen] = 0
Cur_Fire_Cycles[WhichGen] = 0
ActCode[WhichGen] ="-"
WhichColor[WhichGen] = Flammule_BKG_Color
'***************************************************************
' BORDER STATES ARE RESET ONLY WHEN CHEVSURV = "N"
' If chevron should survive, they don't need being reset
'***************************************************************
If ChevSurv = "N" Then
LastBorderState[WhichGen] = "*"
NextBorderState[WhichGen] = "*"
'----------------------------------------------------------
' I am resetting a propagation line that maybe
' was already propagated up or down.
' An "U" one place above or a "D" one place
' below can only be a fruit of the generator
' currently being disabled
'----------------------------------------------------------
If NextBorderState[WhichGen-1] = "U" Then
LastBorderState[WhichGen-1] = "*"
NextBorderState[WhichGen-1] = "*"
EndIf
If NextBorderState[WhichGen+1] = "D" Then
LastBorderState[WhichGen+1] = "*"
NextBorderState[WhichGen+1] = "*"
EndIf
EndIf
Cycle_Activated[WhichGen] = 0
Monitor_Fire_Expired[WhichGen] = 0
If Evenness = "E" Then
Required_Wait_Cycles[WhichGen] = Min_Wait_Cycles
Required_Fire_Cycles[WhichGen] = Min_Fire_Cycles
Else
' WhichGen was set before launching this subroutine
Set_Required_Wait_Cycles()
Set_Required_Fire_Cycles()
EndIf
Last_Wait_Cycle[WhichGen] = OP_ITERATION + Required_Wait_Cycles[WhichGen]
'LAST_FIRE_CYCLE SHOULD NOT BE TOUCHED!
'Otherwise, its reset would impede the deactivation of the «F» Generators of a front
'under the current generator
'------------------------> DEBUG start
If DEBUG And WhichGen < 76 Then '-> DEBUG
Update_Debug_Line()
EndIf '-> DEBUG
'------------------------> DEBUG end
EndIf
EndSub
'=========================
'=========================
' RESET_CURR_GEN_STATE
'=========================
'=========================
Sub Reset_Curr_Gen_State
'=========================================================================
' ...Needed only when collision or conflict detected - or upon spontaneous inactivation.
' ...Needed as a way to avoid the re-activation of inhibited Generators under the current generator.
' ...Needed because of the top-down sequence of the propagation for-next loop.
' Even though I can inhibit a generator by inactivating its NEXT STATE, the next loop cycle would
' query again the current state of the Generator under the current one: unless I change also the
' CURRENT state of the freshly inactivated generator, it would be treated as «F» and propagate again
'=========================================================================
'
' - JUST A CHANGE OF CURRENT STATE IS NEEDED
' - All the other parameters are set by Reset_Next_Gen_State()
' -----------------------------------------------------------------------------------
If curr_prop_stat[WhichGen] <> "A" Then
curr_prop_stat[WhichGen] = "W"
'------------------------> DEBUG start
If DEBUG And WhichGen < 76 Then '-> DEBUG
Update_Debug_Line()
EndIf '-> DEBUG
'------------------------> DEBUG end
EndIf
EndSub
'=========================
'=========================
' SET_REQUIRED_FIRE_CYCLES
'=========================
'=========================
Sub Set_Required_Fire_Cycles
'============================================================
' Depending from the required degree of randomization,
' Required_Fire_Cycles for Generator "WhichGen"
' will be set uniformly to Min_Fire_Cycles, or
' randomized between Min_Fire_Cycles and Max_Fire_Cycles
'============================================================
If Evenness="E" Then
Required_Fire_Cycles[WhichGen] = Min_Fire_Cycles
Else
RETRY_REQ_FIRE_CYCLES:
FireCyclesThisPix = Math.GetRandomNumber(Max_Fire_Cycles)
If FireCyclesThisPix < Min_Fire_Cycles Then
Goto RETRY_REQ_FIRE_CYCLES
EndIf
Required_Fire_Cycles[WhichGen] = WaitCyclesThisPix
EndIf
EndSub
'=========================
'=========================
' SET_REQUIRED_WAIT_CYCLES
'=========================
'=========================
Sub Set_Required_Wait_Cycles
'============================================================
' Depending from the required degree of randomization,
' Required_Wait_Cycles for Generator "WhichGen"
' will be set uniformly to Min_Wait_Cycles, or
' randomized between Min_Wait_Cycles and Max_Wait_Cycles
'============================================================
If Evenness="E" Then
Required_Wait_Cycles[WhichGen] = Min_Wait_Cycles
Else
RETRY_REQ_WAIT_CYCLES:
WaitCyclesThisPix = Math.GetRandomNumber(Max_Wait_Cycles)
If WaitCyclesThisPix < Min_Wait_Cycles Then
Goto RETRY_REQ_WAIT_CYCLES
EndIf
Required_Wait_Cycles[WhichGen] = WaitCyclesThisPix
EndIf
EndSub
'=====================================================
'=====================================================
' SHOW THE SELECTED IMAGE SAMPLE (ACTIVATED BY BUTTONS)
'=====================================================
'=====================================================
Sub Show_Example
Clear_And_Hide_Controls()
ImageWidth=ImageList.GetWidthOfImage(ImageName)
ImageHeight=ImageList.GetHeightOfImage(ImageName)
GraphicsWindow.DrawResizedImage(ImageName,0,50,Math.Round(ImageWidth*0.8),Math.Round(ImageHeight*0.8))
GraphicsWindow.ShowMessage(ImgMsgText,ImgMsgTitle)
Reset_And_Show_Controls()
EndSub
'=========================
'=========================
' UPDATE_DEBUG_LINE
'=========================
'=========================
Sub Update_Debug_Line
If curr_Generator < 76 Then '-> DEBUG
For line = 1 to 75 '-> DEBUG
TextWindow.CursorTop = 1+line '-> DEBUG
TextWindow.CursorLeft = iteration/2+6 '-> DEBUG
' TO DISPLAY LASTBORDERSTATE = REMOVE COMMENT FROM THE LINE BELOW + ADD COMMENT TO THE IF BELOW
'TextWindow.Write(LastBorderState[line]) '-> DEBUG
' TO DISPLAY CURR_PROP_STAT + ACT_CODE= ADD COMMENT FROM THE LINE ABOVE + REMOVE COMMENT FROM THE IF BELOW
If curr_prop_stat[line] = "F" Then
'Instead of the «F» state, I display the "activaton code" of the Generator
TextWindow.Write(ActCode[line]) '-> DEBUG
Else
TextWindow.Write(curr_prop_stat[line]) '-> DEBUG
EndIf
TextWindow.Write(" - CUR "+line+")"+curr_prop_stat[line]+" - NXT "+line+")"+next_prop_stat[line]+" - LAST_W_CY "+Last_Wait_Cycle[line]+" / " + " - MON_F_EXP >"+Monitor_Fire_Expired[line]+" - LAST_F_CY "+Last_Fire_Cycle[Monitor_Fire_Expired[line]] + " - ACT_CODE >"+ActCode[line]+"< ")
'TextWindow.Read() '-> DEBUG
EndFor '-> DEBUG
EndIf '-> DEBUG
EndSub