'====================================== ' 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