Author Topic: Cellular Automata Game Mechanic  (Read 3507 times)

0 Members and 1 Guest are viewing this topic.

Offline justsomeguy

  • Newbie
  • Posts: 47
    • View Profile
Cellular Automata Game Mechanic
« on: April 23, 2021, 05:29:54 pm »
Hello

Before I started working on the 2D physics engine, I was fleshing out a cellular automata game mechanic for a later project. I have since abandoned this approach in favor of another, but it made for an entertaining program.

The idea is similar oeCake, you just draw random stuff and flood it with water or set it on fire. Different materials behave in different ways. So experiment. Be aware this is not intended to be an accurate simulation of these materials. Its just for fun.

Like I said, I abandoned this approach because the 'if' 'then' 'else' 'end if' was getting was out of hand. So, its not entirely finished (Example: oil is not flammable.)
 
Anyways maybe you guys would also enjoy it and you are welcome to use it for your project.
Code: QB64: [Select]
  1. Type tVECTOR2D
  2.     x As Long
  3.     y As Long
  4.  
  5. Type tMATERIAL
  6.     material As Integer
  7.     behavior As Integer
  8.     flammable As Integer
  9.     sleeptime As Long
  10.     update_ticks As Integer
  11.     c As Long ' color
  12.     update As Integer
  13.     lifetime As Integer
  14.     n As String * 20
  15.  
  16. Type tMOUSE
  17.     position As tVECTOR2D
  18.     button1 As Integer
  19.     button2 As Integer
  20.     button3 As Integer
  21.     wheel As Integer
  22.  
  23. Const SIZE_X = 200
  24. Const SIZE_Y = 150
  25. Const SCALE = 4
  26.  
  27. Const cSLEEPTIME = 5 'iterations until cell goes to sleep
  28.  
  29. Const cNUMOFMATERIALS = 15 ' one more than # of actual materials
  30. Const matNOTHING = 0
  31. Const matSAND = 1
  32. Const matLIQUID = 2
  33. Const matSOLID = 3
  34. Const matFOAM = 4 'floats on liquids
  35. Const matACID = 5
  36. Const matRESIDUE = 6
  37. Const matGAS = 7
  38. Const matFIRE = 8
  39. Const matASH = 9
  40. Const matACIDWATER = 10
  41. Const matDRAIN = 11
  42. Const matWATERSOURCE = 12
  43. Const matSTONE = 13
  44. Const matOIL = 14
  45.  
  46. Const reactNOTHING = 0
  47. Const reactAIR = 0
  48. Const reactSAND = 1
  49. Const reactWATER = 2
  50. Const reactWOOD = 3
  51. Const reactFOAM = 4 'floats on liquids
  52. Const reactACID = 5
  53. Const reactRESIDUE = 6
  54. Const reactGAS = 7
  55. Const reactFIRE = 8
  56. Const reactASH = 9
  57. Const reactACIDWATER = 10
  58. Const reactDRAIN = 11
  59. Const reactWATERSOURCE = 12
  60. Const reactSTONE = 13
  61. Const reactOIL = 14
  62.  
  63. 'Dim reaction_matrix(cNUMOFMATERIALS, cNUMOFMATERIALS, 8) As Integer
  64.  
  65. _Title "Cellular Automata"
  66. Screen _NewImage(SIZE_X * SCALE + 200, SIZE_Y * SCALE, 32)
  67.  
  68.  
  69. Dim World(SIZE_X, SIZE_Y) As tMATERIAL
  70.  
  71. Dim mouse As tMOUSE
  72. Dim material_prop(20) As tMATERIAL
  73. Dim Shared freeze, quit As Integer
  74.  
  75. Dim timerOne As Integer
  76. timerOne = _FreeTimer
  77. On Timer(timerOne, 1) renderFPS
  78. Timer(timerOne) On
  79.  
  80.  
  81. Call material_init(material_prop())
  82.  
  83. Do: fps = fps + 1
  84.     Cls
  85.  
  86.     If Not freeze Then Call run_sim(World(), material_prop())
  87.     Call render(World())
  88.     Call render_menu(material_prop(), mouse)
  89.     Call handle_kepress(World(), material_prop())
  90.     Call handle_mouse(World(), mouse, material_prop())
  91.     _Limit 240
  92.     _Display
  93.  
  94. Loop Until quit = 1
  95.  
  96. Sub render_menu (mat_prop() As tMATERIAL, mouse As tMOUSE)
  97.     Dim i As Integer
  98.     Locate 1, 50: Print "FPS:"; fpsLast
  99.     Line (0, 0)-(SIZE_X * SCALE - 1, SIZE_Y * SCALE - 1), _RGB(50, 67, 127), B
  100.  
  101.     For i = 0 To cNUMOFMATERIALS
  102.         Locate i + 1 * 10, 104
  103.         Print mat_prop(i).n
  104.         If i = Abs(mouse.wheel) Then
  105.             Line (102 * 8, i * 16 + 143)-(116 * 8, i * 16 + 158), , B
  106.         End If
  107.     Next
  108.     Locate 2, 104
  109.     Print "Use Mousewheel to"
  110.     Locate 3, 104
  111.     Print "select material."
  112.     Locate 4, 104
  113.     Print "c - Clear screen"
  114.     Locate 5, 104
  115.     Print "s - Save Map"
  116.     Locate 6, 104
  117.     Print "l - Load Map"
  118.     Locate 7, 104
  119.     Print "Left Mouse Button"
  120.     Locate 8, 104
  121.     Print "to Deposit material"
  122. Sub renderFPS
  123.     fpsLast = fps
  124.     fps = 0
  125.  
  126. Sub handle_kepress (world() As tMATERIAL, mat_prop() As tMATERIAL)
  127.     Dim keys As Long
  128.     keys = _KeyHit
  129.     If keys = 27 Then quit = 1
  130.     If keys = 32 Then freeze = Not freeze
  131.  
  132.     If keys > 0 And keys < 256 Then
  133.         If LCase$(Chr$(keys)) = "c" Then
  134.             Call clear_world(world(), mat_prop())
  135.         End If
  136.         If LCase$(Chr$(keys)) = "s" Then
  137.             Call save_world(world(), "CellAuto.ca")
  138.         End If
  139.         If LCase$(Chr$(keys)) = "l" Then
  140.             Call load_world(world(), "CellAuto.ca")
  141.         End If
  142.  
  143.  
  144.     End If
  145.  
  146. Sub save_world (world() As tMATERIAL, filename As String)
  147.     Dim i, j As Integer
  148.  
  149.     Open filename For Output As #1
  150.     Print #1, SIZE_X
  151.     Print #1, SIZE_Y
  152.     For j = 0 To SIZE_Y
  153.         For i = 0 To SIZE_X
  154.             Print #1, world(i, j).material
  155.             Print #1, world(i, j).behavior
  156.             Print #1, world(i, j).flammable
  157.             Print #1, world(i, j).sleeptime
  158.             Print #1, world(i, j).update_ticks
  159.             Print #1, world(i, j).c
  160.             Print #1, world(i, j).update
  161.             Print #1, world(i, j).lifetime
  162.             Print #1, world(i, j).n
  163.         Next
  164.     Next
  165.     Close #1
  166.  
  167. Sub load_world (world() As tMATERIAL, filename As String)
  168.     Dim i, j, Sx, Sy As Integer
  169.     If _FileExists(filename) Then
  170.         Open filename For Input As #1
  171.         Input #1, Sx
  172.         Input #1, Sy
  173.         For j = 0 To Sy
  174.             For i = 0 To Sx
  175.                 Input #1, world(i, j).material
  176.                 Input #1, world(i, j).behavior
  177.                 Input #1, world(i, j).flammable
  178.                 Input #1, world(i, j).sleeptime
  179.                 Input #1, world(i, j).update_ticks
  180.                 Input #1, world(i, j).c
  181.                 Input #1, world(i, j).update
  182.                 Input #1, world(i, j).lifetime
  183.                 Input #1, world(i, j).n
  184.             Next
  185.         Next
  186.         Close #1
  187.     End If
  188.  
  189.  
  190. Sub clear_world (world() As tMATERIAL, mat_prop() As tMATERIAL)
  191.     Dim j, i As Integer
  192.     For j = 0 To SIZE_Y
  193.         For i = 0 To SIZE_X
  194.             world(i, j) = mat_prop(matNOTHING)
  195.         Next
  196.     Next
  197.  
  198. Sub run_sim (world() As tMATERIAL, mat_prop() As tMATERIAL)
  199.     Dim i, j As Long
  200.     Dim UP, DOWN, LEFT, RIGHT As Integer
  201.     Dim process_direction_x, process_direction_y, active_flag As Integer
  202.  
  203.     process_direction_y = 1 - Int((Rnd > .5) * 2)
  204.     start_y = 1: finish_y = SIZE_Y - 1
  205.  
  206.     If process_direction_y < 0 Then
  207.         Swap start_y, finish_y
  208.     End If
  209.  
  210.     For j = start_y To finish_y Step process_direction_y
  211.  
  212.         start_x = 1: finish_x = SIZE_X - 1
  213.         process_direction_x = 1 - Int((Rnd > .5) * 2)
  214.  
  215.         If process_direction_x < 0 Then
  216.             Swap start_x, finish_x
  217.         End If
  218.  
  219.         For i = start_x To finish_x Step process_direction_x
  220.  
  221.             If world(i, j).behavior Then
  222.                 If world(i, j).update = 0 Then ' update tick are used to slow certain materials down
  223.                     If world(i, j).sleeptime > 0 Then ' make sure cell is still active and not sleeping
  224.                         UP = j - 1
  225.                         DOWN = j + 1
  226.                         LEFT = i - 1
  227.                         RIGHT = i + 1
  228.                         ' reaction behavior
  229.                         Select Case world(i, j).material
  230.                             Case reactNOTHING:
  231.                             Case reactSAND:
  232.                             Case reactWATER:
  233.                                 If world(LEFT, UP).material = matACID Then
  234.                                     Call set_mat(world(), mat_prop(), mat_prop(matACIDWATER).material, i, j)
  235.  
  236.                                 Else
  237.                                     If world(i, UP).material = matACID Then
  238.                                         Call set_mat(world(), mat_prop(), mat_prop(matACIDWATER).material, i, j)
  239.  
  240.                                     Else
  241.                                         If world(RIGHT, UP).material = matACID Then
  242.                                             Call set_mat(world(), mat_prop(), mat_prop(matACIDWATER).material, i, j)
  243.  
  244.                                         Else
  245.                                             If world(LEFT, j).material = matACID Then
  246.                                                 Call set_mat(world(), mat_prop(), mat_prop(matACIDWATER).material, i, j)
  247.  
  248.                                             Else
  249.                                                 If world(RIGHT, j).material = matACID Then
  250.                                                     Call set_mat(world(), mat_prop(), mat_prop(matACIDWATER).material, i, j)
  251.  
  252.                                                 Else
  253.                                                     If world(LEFT, DOWN).material = matACID Then
  254.                                                         Call set_mat(world(), mat_prop(), mat_prop(matACIDWATER).material, i, j)
  255.  
  256.                                                     Else
  257.                                                         If world(i, DOWN).material = matACID Then
  258.                                                             Call set_mat(world(), mat_prop(), mat_prop(matACIDWATER).material, i, j)
  259.  
  260.                                                         Else
  261.                                                             If world(RIGHT, DOWN).material = matACID Then
  262.                                                                 Call set_mat(world(), mat_prop(), mat_prop(matACIDWATER).material, i, j)
  263.  
  264.                                                             End If
  265.                                                         End If
  266.                                                     End If
  267.                                                 End If
  268.                                             End If
  269.                                         End If
  270.                                     End If
  271.                                 End If
  272.  
  273.                             Case reactWOOD:
  274.                                 If world(LEFT, UP).material = matACID Then
  275.                                     Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, j)
  276.                                     Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, LEFT, UP)
  277.                                 Else
  278.                                     If world(i, UP).material = matACID Then
  279.                                         Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, j)
  280.                                         Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, UP)
  281.                                     Else
  282.                                         If world(RIGHT, UP).material = matACID Then
  283.                                             Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, j)
  284.                                             Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, RIGHT, UP)
  285.                                         Else
  286.                                             If world(LEFT, j).material = matACID Then
  287.                                                 Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, j)
  288.                                                 Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, LEFT, j)
  289.                                             Else
  290.                                                 If world(RIGHT, j).material = matACID Then
  291.                                                     Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, j)
  292.                                                     Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, RIGHT, j)
  293.                                                 Else
  294.                                                     If world(LEFT, DOWN).material = matACID Then
  295.                                                         Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, j)
  296.                                                         Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, LEFT, DOWN)
  297.                                                     Else
  298.                                                         If world(i, DOWN).material = matACID Then
  299.                                                             Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, j)
  300.                                                             Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, DOWN)
  301.                                                         Else
  302.                                                             If world(RIGHT, DOWN).material = matACID Then
  303.                                                                 Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, i, j)
  304.                                                                 Call set_mat(world(), mat_prop(), mat_prop(matRESIDUE).material, RIGHT, DOWN)
  305.                                                             End If
  306.                                                         End If
  307.                                                     End If
  308.                                                 End If
  309.                                             End If
  310.                                         End If
  311.                                     End If
  312.                                 End If
  313.  
  314.                             Case reactFOAM:
  315.                                 If world(LEFT, UP).material = matACID Then
  316.                                     Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  317.                                     Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, LEFT, UP)
  318.                                 Else
  319.                                     If world(i, UP).material = matACID Then
  320.                                         Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  321.                                         Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, UP)
  322.                                     Else
  323.                                         If world(RIGHT, UP).material = matACID Then
  324.                                             Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  325.                                             Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, RIGHT, UP)
  326.                                         Else
  327.                                             If world(LEFT, j).material = matACID Then
  328.                                                 Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  329.                                                 Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, LEFT, j)
  330.                                             Else
  331.                                                 If world(RIGHT, j).material = matACID Then
  332.                                                     Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  333.                                                     Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, RIGHT, j)
  334.                                                 Else
  335.                                                     If world(LEFT, DOWN).material = matACID Then
  336.                                                         Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  337.                                                         Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, LEFT, DOWN)
  338.                                                     Else
  339.                                                         If world(i, DOWN).material = matACID Then
  340.                                                             Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  341.                                                             Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, DOWN)
  342.                                                         Else
  343.                                                             If world(RIGHT, DOWN).material = matACID Then
  344.                                                                 Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  345.                                                                 Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, RIGHT, DOWN)
  346.                                                             End If
  347.                                                         End If
  348.                                                     End If
  349.                                                 End If
  350.                                             End If
  351.                                         End If
  352.                                     End If
  353.                                 End If
  354.                             Case reactACID:
  355.                             Case reactRESIDUE:
  356.                             Case reactGAS:
  357.                             Case reactFIRE:
  358.                                 active_flag = 0
  359.  
  360.                                 If world(LEFT, UP).material = reactWATER Then
  361.                                     Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, j)
  362.  
  363.                                 Else
  364.                                     If world(i, UP).material = reactWATER Then
  365.                                         Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, j)
  366.  
  367.                                     Else
  368.                                         If world(RIGHT, UP).material = reactWATER Then
  369.                                             Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, j)
  370.  
  371.                                         Else
  372.                                             If world(LEFT, j).material = reactWATER Then
  373.                                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, j)
  374.  
  375.                                             Else
  376.                                                 If world(RIGHT, j).material = reactWATER Then
  377.                                                     Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, j)
  378.  
  379.                                                 Else
  380.                                                     If world(LEFT, DOWN).material = reactWATER Then
  381.                                                         Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, j)
  382.  
  383.                                                     Else
  384.                                                         If world(i, DOWN).material = reactWATER Then
  385.                                                             Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, j)
  386.  
  387.                                                         Else
  388.                                                             If world(RIGHT, DOWN).material = reactWATER Then
  389.                                                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, j)
  390.                                                             Else
  391.                                                                 If world(i, DOWN).material = matSOLID Or world(i, DOWN).material = matFOAM Then
  392.                                                                     If Rnd > .5 Then
  393.                                                                         Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  394.                                                                     Else
  395.                                                                         Call set_mat(world(), mat_prop(), mat_prop(matASH).material, i, j)
  396.                                                                     End If
  397.                                                                     active_flag = 1
  398.                                                                     Call set_mat(world(), mat_prop(), mat_prop(matFIRE).material, i, DOWN)
  399.                                                                 End If
  400.                                                                 If world(i, UP).material = reactWOOD Or world(i, UP).material = reactFOAM Then
  401.                                                                     Call set_mat(world(), mat_prop(), mat_prop(reactFIRE).material, i, UP)
  402.                                                                     If Rnd > .5 Then
  403.                                                                         Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  404.                                                                     Else
  405.                                                                         Call set_mat(world(), mat_prop(), mat_prop(reactASH).material, i, j)
  406.                                                                     End If
  407.                                                                     active_flag = 1
  408.                                                                 End If
  409.  
  410.                                                                 If world(LEFT, j).material = matSOLID Or world(LEFT, j).material = matFOAM Then
  411.                                                                     If Rnd > .5 Then
  412.                                                                         Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  413.                                                                     Else
  414.                                                                         Call set_mat(world(), mat_prop(), mat_prop(matASH).material, i, j)
  415.                                                                     End If
  416.                                                                     Call set_mat(world(), mat_prop(), mat_prop(matFIRE).material, LEFT, j)
  417.                                                                     active_flag = 1
  418.                                                                 End If
  419.                                                                 If world(RIGHT, j).material = matSOLID Or world(RIGHT, j).material = matFOAM Then
  420.                                                                     If Rnd > .5 Then
  421.                                                                         Call set_mat(world(), mat_prop(), mat_prop(matGAS).material, i, j)
  422.                                                                     Else
  423.                                                                         Call set_mat(world(), mat_prop(), mat_prop(matASH).material, i, j)
  424.                                                                     End If
  425.  
  426.                                                                     Call set_mat(world(), mat_prop(), mat_prop(matFIRE).material, RIGHT, j)
  427.                                                                     active_flag = 1
  428.                                                                 End If
  429.  
  430.                                                             End If
  431.                                                         End If
  432.                                                     End If
  433.                                                 End If
  434.                                             End If
  435.                                         End If
  436.                                     End If
  437.                                 End If
  438.  
  439.                                 If active_flag = 0 Then
  440.                                     world(i, j).lifetime = world(i, j).lifetime - 1
  441.                                     If world(i, j).lifetime < 1 Then Call set_mat(world(), mat_prop(), mat_prop(matNOTHING).material, i, j)
  442.                                 Else
  443.                                     world(i, j).sleeptime = 50
  444.                                     world(i, j).update = 0
  445.                                 End If
  446.                             Case reactASH:
  447.                             Case reactACIDWATER:
  448.                                 If world(LEFT, DOWN).material = matACID Or world(LEFT, DOWN).material = reactWATER Then
  449.  
  450.                                     Call set_mat(world(), mat_prop(), mat_prop(reactACIDWATER).material, LEFT, DOWN)
  451.                                 Else
  452.                                     If world(i, DOWN).material = matACID Or world(i, DOWN).material = reactWATER Then
  453.  
  454.                                         Call set_mat(world(), mat_prop(), mat_prop(reactACIDWATER).material, i, DOWN)
  455.                                     Else
  456.                                         If world(RIGHT, DOWN).material = matACID Or world(RIGHT, DOWN).material = reactWATER Then
  457.                                             Call set_mat(world(), mat_prop(), mat_prop(reactACIDWATER).material, RIGHT, DOWN)
  458.                                         End If
  459.                                     End If
  460.                                 End If
  461.                             Case reactDRAIN:
  462.                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, LEFT, UP)
  463.                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, UP)
  464.                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, RIGHT, UP)
  465.                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, LEFT, j)
  466.                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, RIGHT, j)
  467.                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, LEFT, DOWN)
  468.                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, i, DOWN)
  469.                                 Call set_mat(world(), mat_prop(), mat_prop(reactAIR).material, RIGHT, DOWN)
  470.                             Case reactWATERSOURCE:
  471.                                 If world(LEFT, UP).material = reactNOTHING Then Call set_mat(world(), mat_prop(), mat_prop(reactWATER).material, LEFT, UP)
  472.                                 If world(i, UP).material = reactNOTHING Then Call set_mat(world(), mat_prop(), mat_prop(reactWATER).material, i, UP)
  473.                                 If world(RIGHT, UP).material = reactNOTHING Then Call set_mat(world(), mat_prop(), mat_prop(reactWATER).material, RIGHT, UP)
  474.                                 If world(LEFT, j).material = reactNOTHING Then Call set_mat(world(), mat_prop(), mat_prop(reactWATER).material, LEFT, j)
  475.                                 If world(RIGHT, j).material = reactNOTHING Then Call set_mat(world(), mat_prop(), mat_prop(reactWATER).material, RIGHT, j)
  476.                                 If world(LEFT, DOWN).material = reactNOTHING Then Call set_mat(world(), mat_prop(), mat_prop(reactWATER).material, LEFT, DOWN)
  477.                                 If world(i, DOWN).material = reactNOTHING Then Call set_mat(world(), mat_prop(), mat_prop(reactWATER).material, i, DOWN)
  478.                                 If world(RIGHT, DOWN).material = reactNOTHING Then Call set_mat(world(), mat_prop(), mat_prop(reactWATER).material, RIGHT, DOWN)
  479.  
  480.                         End Select
  481.                         'movement behavior below
  482.                         Select Case world(i, j).behavior
  483.                             Case matSAND:
  484.                                 'Check DOWN
  485.                                 If world(i, DOWN).behavior = matNOTHING Or world(i, DOWN).behavior = matLIQUID Or world(i, DOWN).behavior = matGAS Or world(i, DOWN).material = reactOIL Then
  486.                                     Call move_mat(world(), mat_prop(), i, j, i, DOWN)
  487.                                 Else
  488.                                     'Check LEFT DOWN
  489.                                     If world(LEFT, DOWN).behavior = matNOTHING Or world(LEFT, DOWN).behavior = matLIQUID Or world(LEFT, DOWN).behavior = matGAS Or world(LEFT, DOWN).material = reactOIL Then
  490.                                         Call move_mat(world(), mat_prop(), i, j, LEFT, DOWN)
  491.                                     Else
  492.                                         'Check RIGHT DOWN
  493.                                         If world(RIGHT, DOWN).behavior = matNOTHING Or world(RIGHT, DOWN).behavior = matLIQUID Or world(RIGHT, DOWN).behavior = matGAS Or world(RIGHT, DOWN).material = reactOIL Then
  494.                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, DOWN)
  495.                                         End If
  496.                                     End If
  497.                                 End If
  498.                             Case matLIQUID:
  499.                                 If world(i, DOWN).behavior = matNOTHING Or world(i, DOWN).behavior = matFOAM Or world(i, DOWN).behavior = matGAS Then
  500.                                     Call move_mat(world(), mat_prop(), i, j, i, DOWN)
  501.                                 Else
  502.                                     ' if both left down and right down are available then RNG the direction
  503.                                     If (world(LEFT, DOWN).behavior = matNOTHING Or world(LEFT, DOWN).behavior = matFOAM Or world(LEFT, DOWN).behavior = matGAS) And _
  504.                                        (world(RIGHT, DOWN).behavior = matNOTHING Or world(RIGHT, DOWN).behavior = matFOAM Or world(RIGHT, DOWN).behavior = matGAS) Then
  505.                                         If Rnd > .5 Then
  506.                                             Call move_mat(world(), mat_prop(), i, j, LEFT, DOWN)
  507.                                         Else
  508.                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, DOWN)
  509.                                         End If
  510.                                     Else
  511.                                         'Check LEFT DOWN
  512.                                         If world(LEFT, DOWN).behavior = matNOTHING Or world(LEFT, DOWN).behavior = matFOAM Or world(LEFT, DOWN).behavior = matGAS Then
  513.                                             Call move_mat(world(), mat_prop(), i, j, LEFT, DOWN)
  514.                                         Else
  515.                                             'Check RIGHT DOWN
  516.                                             If world(RIGHT, DOWN).behavior = matNOTHING Or world(RIGHT, DOWN).behavior = matFOAM Or world(RIGHT, DOWN).behavior = matGAS Then
  517.                                                 Call move_mat(world(), mat_prop(), i, j, RIGHT, DOWN)
  518.                                             Else
  519.                                                 If (world(LEFT, j).behavior = matNOTHING Or world(LEFT, j).behavior = matFOAM Or world(LEFT, j).behavior = matGAS) And _
  520.                                                    (world(RIGHT, j).behavior = matNOTHING Or world(RIGHT, j).behavior = matFOAM Or world(RIGHT, j).behavior = matgas) Then
  521.                                                     ' if both left  and right  are available then RNG the direction
  522.                                                     If Rnd > .5 Then
  523.                                                         Call move_mat(world(), mat_prop(), i, j, LEFT, j)
  524.                                                     Else
  525.                                                         Call move_mat(world(), mat_prop(), i, j, RIGHT, j)
  526.                                                     End If
  527.                                                 Else
  528.                                                     ' Check LEFT
  529.                                                     If world(LEFT, j).behavior = matNOTHING Or world(LEFT, j).behavior = matFOAM Or world(LEFT, j).behavior = matGAS Then
  530.                                                         Call move_mat(world(), mat_prop(), i, j, LEFT, j)
  531.                                                     Else
  532.                                                         'Check RIGHT
  533.                                                         If world(RIGHT, j).behavior = matNOTHING Or world(RIGHT, j).behavior = matFOAM Or world(RIGHT, j).behavior = matGAS Then
  534.                                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, j)
  535.                                                         End If
  536.                                                     End If
  537.                                                 End If
  538.                                             End If
  539.                                         End If
  540.                                     End If
  541.                                 End If
  542.                             Case matSOLID:
  543.                                 'Do Nothing no movement
  544.  
  545.                             Case matFOAM:
  546.                                 'Check DOWN
  547.                                 If world(i, DOWN).behavior = matNOTHING Or world(i, DOWN).behavior = matGAS Then
  548.                                     Call move_mat(world(), mat_prop(), i, j, i, DOWN)
  549.                                 Else
  550.                                     If (world(LEFT, DOWN).behavior = matNOTHING Or world(LEFT, DOWN).behavior = matGAS) And (world(RIGHT, DOWN).behavior = matNOTHING Or world(RIGHT, DOWN).behavior = matGAS) Then
  551.                                         If Rnd > .5 Then
  552.                                             Call move_mat(world(), mat_prop(), i, j, LEFT, DOWN)
  553.                                         Else
  554.                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, DOWN)
  555.                                         End If
  556.                                     Else
  557.                                         'Check LEFT DOWN
  558.                                         If world(LEFT, DOWN).behavior = matNOTHING Or world(LEFT, DOWN).behavior = matGAS Then
  559.                                             Call move_mat(world(), mat_prop(), i, j, LEFT, DOWN)
  560.                                         Else
  561.                                             'Check RIGHT DOWN
  562.                                             If world(RIGHT, DOWN).behavior = matNOTHING Or world(RIGHT, DOWN).behavior = matGAS Then
  563.                                                 Call move_mat(world(), mat_prop(), i, j, RIGHT, DOWN)
  564.                                             Else
  565.                                                 'Check UP
  566.                                                 If world(i, UP).behavior = matLIQUID Then
  567.                                                     Call move_mat(world(), mat_prop(), i, j, i, UP)
  568.                                                 Else
  569.                                                     If world(LEFT, UP).behavior = matLIQUID And world(RIGHT, UP).behavior = matLIQUID Then
  570.                                                         If Rnd > .5 Then
  571.                                                             Call move_mat(world(), mat_prop(), i, j, LEFT, UP)
  572.                                                         Else
  573.                                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, UP)
  574.                                                         End If
  575.                                                     Else
  576.                                                         'Check LEFT UP
  577.                                                         If world(LEFT, UP).behavior = matLIQUID Then
  578.                                                             Call move_mat(world(), mat_prop(), i, j, LEFT, UP)
  579.                                                         Else
  580.                                                             'Check RIGHT UP
  581.                                                             If world(RIGHT, UP).behavior = matLIQUID Then
  582.                                                                 Call move_mat(world(), mat_prop(), i, j, RIGHT, UP)
  583.                                                             Else
  584.                                                                 If (world(LEFT, j).behavior = matLIQUID Or world(LEFT, j).behavior = matNOTHING Or world(LEFT, j).behavior = matGAS) And (world(RIGHT, j).behavior = matLIQUID Or world(RIGHT, j).behavior = matNOTHING Or world(RIGHT, j).behavior = matGAS) Then
  585.                                                                     If Rnd > .5 Then
  586.                                                                         Call move_mat(world(), mat_prop(), i, j, LEFT, j)
  587.                                                                     Else
  588.                                                                         Call move_mat(world(), mat_prop(), i, j, RIGHT, j)
  589.                                                                     End If
  590.                                                                 Else
  591.                                                                     'Check LEFT
  592.                                                                     If world(LEFT, j).behavior = matLIQUID Or world(LEFT, j).behavior = matNOTHING Or world(LEFT, j).behavior = matGAS Then
  593.                                                                         Call move_mat(world(), mat_prop(), i, j, LEFT, j)
  594.                                                                     Else
  595.                                                                         'Check RIGHT
  596.                                                                         If world(RIGHT, j).behavior = matLIQUID Or world(RIGHT, j).behavior = matNOTHING Or world(RIGHT, j).behavior = matGAS Then
  597.                                                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, j)
  598.                                                                         End If
  599.                                                                     End If
  600.                                                                 End If
  601.                                                             End If
  602.                                                         End If
  603.                                                     End If
  604.                                                 End If
  605.                                             End If
  606.                                         End If
  607.                                     End If
  608.                                 End If
  609.  
  610.                             Case matGAS:
  611.                                 If world(i, UP).behavior = matNOTHING Then
  612.                                     Call move_mat(world(), mat_prop(), i, j, i, UP)
  613.                                 Else
  614.                                     ' if both left up and right up are available then RNG the direction
  615.                                     If (world(LEFT, UP).behavior = matNOTHING) And (world(RIGHT, UP).behavior = matNOTHING) Then
  616.                                         If Rnd > .5 Then
  617.                                             Call move_mat(world(), mat_prop(), i, j, LEFT, UP)
  618.                                         Else
  619.                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, UP)
  620.                                         End If
  621.                                     Else
  622.                                         'Check LEFT up
  623.                                         If world(LEFT, UP).behavior = matNOTHING Then
  624.                                             Call move_mat(world(), mat_prop(), i, j, LEFT, UP)
  625.                                         Else
  626.                                             'Check RIGHT up
  627.                                             If world(RIGHT, UP).behavior = matNOTHING Then
  628.                                                 Call move_mat(world(), mat_prop(), i, j, RIGHT, UP)
  629.                                             Else
  630.                                                 If (world(LEFT, j).behavior = matNOTHING) And (world(RIGHT, j).behavior = matNOTHING) Then
  631.                                                     ' if both left  and right  are available then RNG the direction
  632.                                                     If Rnd > .5 Then
  633.                                                         Call move_mat(world(), mat_prop(), i, j, LEFT, j)
  634.                                                     Else
  635.                                                         Call move_mat(world(), mat_prop(), i, j, RIGHT, j)
  636.                                                     End If
  637.                                                 Else
  638.                                                     ' Check LEFT
  639.                                                     If world(LEFT, j).behavior = matNOTHING Then
  640.                                                         Call move_mat(world(), mat_prop(), i, j, LEFT, j)
  641.                                                     Else
  642.                                                         'Check RIGHT
  643.                                                         If world(RIGHT, j).behavior = matNOTHING Then
  644.                                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, j)
  645.                                                         End If
  646.                                                     End If
  647.                                                 End If
  648.                                             End If
  649.                                         End If
  650.                                     End If
  651.                                 End If
  652.                             Case matFIRE:
  653.                             Case matDRAIN:
  654.                             Case matWATERSOURCE:
  655.                             Case matSTONE:
  656.                             Case matOIL:
  657.                                 If world(i, DOWN).behavior = matNOTHING Or world(i, DOWN).behavior = matFOAM Or world(i, DOWN).behavior = matGAS Then
  658.                                     Call move_mat(world(), mat_prop(), i, j, i, DOWN)
  659.                                 Else
  660.                                     ' if both left down and right down are available then RNG the direction
  661.                                     If (world(LEFT, DOWN).behavior = matNOTHING Or world(LEFT, DOWN).behavior = matFOAM Or world(LEFT, DOWN).behavior = matGAS) and _
  662.                                        (world(RIGHT, DOWN).behavior = matNOTHING Or world(RIGHT, DOWN).behavior = matFOAM Or world(RIGHT, DOWN).behavior = matGAS) Then
  663.                                         If Rnd > .5 Then
  664.                                             Call move_mat(world(), mat_prop(), i, j, LEFT, DOWN)
  665.                                         Else
  666.                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, DOWN)
  667.                                         End If
  668.                                     Else
  669.                                         'Check LEFT DOWN
  670.                                         If world(LEFT, DOWN).behavior = matNOTHING Or world(LEFT, DOWN).behavior = matFOAM Or world(LEFT, DOWN).behavior = matGAS Then
  671.                                             Call move_mat(world(), mat_prop(), i, j, LEFT, DOWN)
  672.                                         Else
  673.                                             'Check RIGHT DOWN
  674.                                             If world(RIGHT, DOWN).behavior = matNOTHING Or world(RIGHT, DOWN).behavior = matFOAM Or world(RIGHT, DOWN).behavior = matGAS Then
  675.                                                 Call move_mat(world(), mat_prop(), i, j, RIGHT, DOWN)
  676.                                             Else
  677.                                                 If world(i, UP).material = reactWATER Then
  678.                                                     Call move_mat(world(), mat_prop(), i, j, i, UP)
  679.                                                 Else
  680.                                                     If world(LEFT, UP).material = reactWATER Then
  681.                                                         Call move_mat(world(), mat_prop(), i, j, LEFT, UP)
  682.                                                     Else
  683.                                                         If world(RIGHT, UP).material = reactWATER Then
  684.                                                             Call move_mat(world(), mat_prop(), i, j, RIGHT, UP)
  685.                                                         Else
  686.                                                             If (world(LEFT, j).behavior = matNOTHING Or world(LEFT, j).behavior = matFOAM Or world(LEFT, j).behavior = matGAS Or world(LEFT, j).material = reactWATER) And _
  687.                                                                (world(RIGHT, j).behavior = matNOTHING Or world(RIGHT, j).behavior = matFOAM Or world(RIGHT, j).behavior = matGAS Or world(RIGHT, j).material = reactWATER) Then
  688.                                                                 ' if both left  and right  are available then RNG the direction
  689.                                                                 If Rnd > .5 Then
  690.                                                                     Call move_mat(world(), mat_prop(), i, j, LEFT, j)
  691.                                                                 Else
  692.                                                                     Call move_mat(world(), mat_prop(), i, j, RIGHT, j)
  693.                                                                 End If
  694.                                                             Else
  695.                                                                 ' Check LEFT
  696.                                                                 If world(LEFT, j).behavior = matNOTHING Or world(LEFT, j).behavior = matFOAM Or world(LEFT, j).behavior = matGAS Or world(LEFT, j).material = reactWATER Then
  697.                                                                     Call move_mat(world(), mat_prop(), i, j, LEFT, j)
  698.                                                                 Else
  699.                                                                     'Check RIGHT
  700.                                                                     If world(RIGHT, j).behavior = matNOTHING Or world(RIGHT, j).behavior = matFOAM Or world(RIGHT, j).behavior = matGAS Or world(RIGHT, j).material = reactWATER Then
  701.                                                                         Call move_mat(world(), mat_prop(), i, j, RIGHT, j)
  702.  
  703.                                                                     End If
  704.                                                                 End If
  705.                                                             End If
  706.                                                         End If
  707.                                                     End If
  708.                                                 End If
  709.                                             End If
  710.                                         End If
  711.                                     End If
  712.                                 End If
  713.  
  714.                         End Select
  715.                         If world(LEFT, j).behavior <> matFIRE Then 'Never put fire to sleep
  716.                             world(i, j).sleeptime = world(i, j).sleeptime - 1
  717.                         End If
  718.                     End If
  719.                 End If
  720.             End If
  721.         Next
  722.     Next
  723.  
  724.  
  725. Sub render (world() As tMATERIAL)
  726.     Dim i, j As Integer
  727.     For j = 1 To SIZE_Y - 1
  728.         For i = 1 To SIZE_X - 1
  729.             Line (i * SCALE, j * SCALE)-(i * SCALE + (SCALE - 1), j * SCALE + (SCALE - 1)), world(i, j).c, BF
  730.             If world(i, j).update > 0 Then
  731.                 world(i, j).update = world(i, j).update - 1 ' decrement tick count for next update
  732.             End If
  733.         Next
  734.     Next
  735.  
  736. Sub set_mat (world() As tMATERIAL, mat_prop() As tMATERIAL, material As Integer, x As Integer, y As Integer)
  737.  
  738.     world(x, y) = mat_prop(material)
  739.     Call update_lifetime(world(), x, y, cSLEEPTIME) ' wake up neighboring cells
  740.  
  741.  
  742. Sub move_mat (world() As tMATERIAL, mat_prop() As tMATERIAL, x As Integer, y As Integer, xm As Integer, ym As Integer)
  743.     Dim SWAPMat As tMATERIAL
  744.     SWAPMat = world(xm, ym)
  745.     world(xm, ym) = world(x, y)
  746.     world(x, y) = SWAPMat
  747.     world(x, y).update = mat_prop(world(x, y).material).update_ticks ' cell has been processed this cycle
  748.     world(xm, ym).update = mat_prop(world(xm, ym).material).update_ticks ' cell has been processed this cycle
  749.     Call update_lifetime(world(), x, y, cSLEEPTIME) ' wake up neighboring cells
  750.     Call update_lifetime(world(), xm, ym, cSLEEPTIME) ' wake up neighboring cells
  751.  
  752. Sub update_lifetime (world() As tMATERIAL, x As Integer, y As Integer, l As Integer)
  753.     'wake up neighboring cells as they may be affected by nearby changes
  754.     For j = -1 To 1
  755.         For i = -1 To 1
  756.             If x + i > 0 And y + j > 0 And x + i < SIZE_X And y + j < SIZE_Y Then
  757.                 If world(i + x, j + y).material > matNOTHING Then
  758.                     world(x + i, y + j).sleeptime = l
  759.                 End If
  760.             End If
  761.         Next
  762.     Next
  763.  
  764. Sub material_init (ms() As tMATERIAL)
  765.     Dim i, r, g, b, behavior, update, life As Integer
  766.  
  767.     Data "air",0,0,0,0,0,-1,"sand",1,1,166,172,127,-1,"water",2,1,67,72,183,-1,"wood",3,1,111,72,0,-1
  768.     Data "foam",4,1,255,255,255,-1,"acid",2,4,17,216,22,-1,"residue",1,6,127,67,127,-1,"gas",7,10,128,127,127,-1
  769.     Data "fire",8,20,255,64,0,10,"ash",1,4,32,32,32,-1,"acidwater",2,10,6,83,6,-1,"drain",11,4,44,28,28,-1
  770.     Data "water source",12,1,44,28,28,-1,"stone",13,1,127,127,127,-1,"oil",14,2,20,20,20,-1
  771.     For i = 0 To cNUMOFMATERIALS - 1
  772.         Read ms(i).n
  773.         Read behavior
  774.         Read update
  775.         Read r
  776.         Read g
  777.         Read b
  778.         Read life
  779.         ms(i).c = _RGB32(r, g, b)
  780.         ms(i).behavior = behavior
  781.         ms(i).material = i
  782.         ms(i).sleeptime = cSLEEPTIME
  783.         ms(i).update = update
  784.         ms(i).update_ticks = update
  785.         ms(i).lifetime = life
  786.     Next i
  787.  
  788.  
  789. Sub handle_mouse (world() As tMATERIAL, mouse As tMOUSE, mat_prop() As tMATERIAL)
  790.     Dim w, i, j As Integer
  791.         mouse.position.x = _MouseX: mouse.position.y = _MouseY
  792.         mouse.button1 = _MouseButton(1)
  793.         mouse.button2 = _MouseButton(2)
  794.         mouse.button3 = _MouseButton(3)
  795.         mouse.wheel = ((mouse.wheel + _MouseWheel) Mod cNUMOFMATERIALS)
  796.     End If
  797.     w = Abs(mouse.wheel)
  798.     If mouse.button1 Then
  799.         If mouse.position.x > 1 And mouse.position.x < SIZE_X * SCALE - 1 And mouse.position.y > 1 And mouse.position.y < SIZE_Y * SCALE - 1 Then
  800.             For j = -1 To 1
  801.                 For i = -1 To 1
  802.                     Call set_mat(world(), mat_prop(), mat_prop(w).material, mouse.position.x / SCALE + i, mouse.position.y / SCALE + j)
  803.                 Next
  804.             Next
  805.         End If
  806.     End If
  807.  
  808.  
  809.  

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: Cellular Automata Game Mechanic
« Reply #1 on: April 24, 2021, 12:24:08 am »
Quote
'if' 'then' 'else' 'end if'

I used to code with ELSE  but found myself thinking in terms of ELSE as if the logic depended on it.  Then when I discovered assembler I found out that ELSE does not really exist.   In assembler it is either one condition or the other you got to be very specific.  The same thing goes for high level languages.

ELSE is strictly implied logic.  It might save some code, but code using ELSE  is harder to read and sometimes creates unintended bugs example:

if var > 100 then
do this

else do that

end if

The ELSE implies   if var <= 100 then do that

but lets say the intention was

if var = 100 then do that

so that is a classic bug created by ELSE.

The proper way to code it is:

if var > 100 then
do this
end if

if var <= 100 then
do that
end if

The code in it's proper form is much easier to read and debug.

« Last Edit: April 24, 2021, 12:35:15 am by NOVARSEG »

Offline justsomeguy

  • Newbie
  • Posts: 47
    • View Profile
Re: Cellular Automata Game Mechanic
« Reply #2 on: April 24, 2021, 09:12:22 am »
This part of the reason I abandoned this approach.

Cellular automata is scanning your cells and each cell would make a decision on how to move or react based upon its neighbors.

Issues arise when you want to add some randomness to it behavior. For instance you have a sand pile. You drop a grain of sand directly on the very apex of the pile. Which side will it roll down? 'IF THEN ELSE'  it will roll down the side that meets the criteria first. Its difficult to add randomness.

Another issue is when you have multiple criteria that is true and you want to prioritize certain behaviors over others. As build your behavior tree it get more and more tedious modify all the 'IF THEN ELSE' statements.

I've moved to the idea of a look up table that has a priorities of conditions and reactions and if it has multiple criteria that is true and at the same priority, it will pick an action at random. This approach adds flexibility and easy modification. However as you add new materials the table grows exponentially.

Thanks for your feedback!