Author Topic: Hexagonal Life  (Read 6961 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Hexagonal Life
« on: September 25, 2019, 09:01:12 am »
Same set of rules as Conway's Life played out with Hexagonal Cells that have 6 neighbors to count, it seems to have a space filling and stabilizing nature for small seed starts:
Code: QB64: [Select]
  1. OPTION _EXPLICIT 'Bplus started 2019-09-23 from Hex Minesweeper Custom Field
  2. DEFINT A-Z
  3. CONST cellR = 20 ' which makes the following constant
  4. CONST xspacing! = 2 * cellR * COS(_D2R(30))
  5. CONST yspacing! = cellR * (1 + SIN(_D2R(30)))
  6.  
  7. TYPE cell
  8.     x AS INTEGER
  9.     y AS INTEGER
  10.     L AS INTEGER
  11.  
  12. DIM SHARED xmax, ymax, Xarrd, Yarrd 'set all this in customField sub
  13.  
  14.  
  15. '      note: To preserve symmetry when cells hit boundries with a symmetric seed started in middle:
  16. '            y should be odd for 1 cell center x axis, on a shorter inner row
  17. '            If x is odd then one cell is marked in center.
  18. '            If x is even the left one of two center cells will be marked, toggle the one to right also (for symmetric seed).
  19.  
  20. Xarrd = 21 ' the top left cell has been hacked to duplicate the top right cell, to preserve symmetric seeds through a run
  21.  
  22. Yarrd = 21 'y should always be odd top preserve symmetry of center symmetric seed
  23.  
  24. xmax = (Xarrd + 2) * xspacing!: ymax = (Yarrd + 2) * yspacing!
  25.  
  26. SCREEN _NEWIMAGE(xmax, ymax, 32)
  27. _SCREENMOVE (1280 - xmax) / 2 + 60, (760 - ymax) / 2
  28. DIM SHARED b(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS cell, ng(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS INTEGER 'oversize the board to make it easy to count
  29. DIM x, y, xoffset!, xStop, nc, c, r, mb, kh&
  30.  
  31.     _TITLE "Hexagon Life: Left Click to Toggle Cells On/Off, Right Click to Start Run, Escape to Quit"
  32.     ' set x, y for cells and mark ceter cell(s)
  33.     FOR y = 1 TO Yarrd
  34.         IF y MOD 2 = 0 THEN
  35.             xoffset! = .5 * xspacing!: xStop = Xarrd - 1
  36.         ELSE
  37.             xoffset! = 0: xStop = Xarrd
  38.         END IF
  39.         FOR x = 1 TO xStop
  40.             b(x, y).x = x * xspacing! + xoffset! + .5 * xspacing!
  41.             b(x, y).y = y * yspacing! + .5 * yspacing!
  42.             IF x = INT(Xarrd / 2 + .5) AND y = INT(Yarrd / 2 + .5) THEN b(x, y).L = 1 ELSE b(x, y).L = 0 'mark middle cell
  43.             showCell x, y
  44.         NEXT
  45.     NEXT
  46.     _DISPLAY
  47.  
  48.     'setup seed by toggling cells on and off
  49.     WHILE mb <> 2
  50.         kh& = _KEYHIT
  51.         IF kh& = 27 THEN EXIT DO
  52.         mb = 0: c = 0: r = 0
  53.         getCell c, r, mb
  54.         IF mb = 1 THEN
  55.             b(c, r).L = 1 - b(c, r).L
  56.             showCell c, r
  57.         END IF
  58.         _DISPLAY
  59.         _LIMIT 60
  60.     WEND
  61.     mb = 0
  62.     _TITLE "Hexagon Life: Spacebar to Restart/Reseed, Escape to Quit"
  63.     WHILE kh& <> 32 AND kh& <> 27
  64.         kh& = _KEYHIT
  65.         'count the neighbors
  66.         FOR y = 1 TO Yarrd
  67.             IF y MOD 2 = 0 THEN
  68.                 xoffset! = .5 * xspacing!: xStop = Xarrd - 1
  69.             ELSE
  70.                 xoffset! = 0: xStop = Xarrd
  71.             END IF
  72.             FOR x = 1 TO xStop
  73.                 '2 sets of neighbors depending if x offset or not
  74.                 IF xoffset! > .05 THEN
  75.                     nc = b(x, y - 1).L + b(x + 1, y - 1).L + b(x - 1, y).L
  76.                     nc = nc + b(x + 1, y).L + b(x, y + 1).L + b(x + 1, y + 1).L
  77.                 ELSE
  78.                     nc = b(x - 1, y - 1).L + b(x, y - 1).L + b(x - 1, y).L
  79.                     nc = nc + b(x + 1, y).L + b(x - 1, y + 1).L + b(x, y + 1).L
  80.                 END IF
  81.                 IF (nc = 3 AND b(x, y).L = 1) OR nc = 2 THEN ng(x, y) = 1 ELSE ng(x, y) = 0
  82.             NEXT
  83.         NEXT
  84.         LINE (0, 0)-(xmax, ymax), &H44000000, BF
  85.         FOR y = 1 TO Yarrd 'transfer data from ng to b().l and show cell
  86.             IF y MOD 2 = 0 THEN
  87.                 xStop = Xarrd - 1
  88.             ELSE
  89.                 xStop = Xarrd
  90.             END IF
  91.             FOR x = 1 TO xStop
  92.                 b(x, y).L = ng(x, y)
  93.                 showCell x, y
  94.             NEXT
  95.             'fix symmetry for top left corner, match x at other end for bi-lat symmetry
  96.             b(1, 1).L = b(Xarrd, 1).L
  97.             showCell 1, 1
  98.         NEXT
  99.         _DISPLAY
  100.         _LIMIT 1
  101.     WEND
  102.     IF kh& = 27 THEN EXIT DO
  103.     kh& = 0
  104.  
  105. SUB showCell (c, r)
  106.     DIM da, x!, y!, lastx!, lasty!, clr AS _UNSIGNED LONG
  107.     IF r MOD 2 = 0 THEN
  108.         IF c < 1 OR c > Xarrd - 1 THEN EXIT SUB
  109.     ELSE
  110.         IF c < 1 OR c > Xarrd THEN EXIT SUB
  111.     END IF
  112.     IF r < 1 OR r > Yarrd THEN EXIT SUB
  113.     IF b(c, r).L = 1 THEN clr = &HFFFFFFFF ELSE clr = &HFF000000
  114.     lastx! = b(c, r).x + cellR * COS(_D2R(-30))
  115.     lasty! = b(c, r).y + cellR * SIN(_D2R(-30))
  116.     FOR da = 30 TO 330 STEP 60
  117.         x! = b(c, r).x + cellR * COS(_D2R(da))
  118.         y! = b(c, r).y + cellR * SIN(_D2R(da))
  119.         LINE (lastx!, lasty!)-(x!, y!), &HFFFF00FF
  120.         lastx! = x!: lasty! = y!
  121.     NEXT
  122.     PAINT (b(c, r).x, b(c, r).y), clr, &HFFFF00FF
  123.     'debug
  124.     'cText b(c, r).x, b(c, r).y, 16, &HFF888888, STR$(c) + "," + STR$(r)
  125.  
  126. SUB getCell (returnCol AS INTEGER, returnRow AS INTEGER, mbNum AS INTEGER)
  127.     DIM m, mx, my, mb1, mb2, r, c
  128.     mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  129.     IF mb1 THEN mbNum = 1
  130.     IF mb2 THEN mbNum = 2
  131.     IF mb1 OR mb2 THEN '                      get last place mouse button was down
  132.         WHILE mb1 OR mb2 '                    wait for mouse button release as a "click"
  133.             m = _MOUSEINPUT: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  134.             mx = _MOUSEX: my = _MOUSEY
  135.             'LOCATE 1, 1: PRINT SPACE$(50)
  136.             'LOCATE 1, 1: PRINT mx, my, .5 * xspacing!
  137.             _DISPLAY
  138.         WEND
  139.         FOR r = 1 TO Yarrd
  140.             FOR c = 1 TO Xarrd
  141.                 IF ((mx - b(c, r).x) ^ 2 + (my - b(c, r).y) ^ 2) ^ .5 < .5 * xspacing! THEN
  142.                     returnCol = c: returnRow = r: EXIT SUB
  143.                 END IF
  144.             NEXT
  145.         NEXT
  146.         mbNum = 0 'still here then clicked wrong
  147.     END IF
  148.  
  149. 'debug
  150. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  151.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  152.     fg = _DEFAULTCOLOR
  153.     'screen snapshot
  154.     cur& = _DEST
  155.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  156.     _DEST I&
  157.     COLOR K, _RGBA32(0, 0, 0, 0)
  158.     _PRINTSTRING (0, 0), txt$
  159.     mult = textHeight / 16
  160.     xlen = LEN(txt$) * 8 * mult
  161.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  162.     COLOR fg
  163.     _FREEIMAGE I&
  164.  
  165.  

If you had enjoyed exploring Conway's Life, you'll like exploring this one too I think. In a way I find this Life version more robust.

I am a lover of symmetry so this code has been hacked a little to keep a symmetric seed start symmetric throughout the run, bilateral left/right in particular.
Hex Life Sample seed.PNG
* Hex Life Sample seed.PNG (Filesize: 34.38 KB, Dimensions: 801x714, Views: 182)
Hex Life Run a 6 or generations.PNG
* Hex Life Run a 6 or generations.PNG (Filesize: 41.7 KB, Dimensions: 802x714, Views: 172)
Hex Life Stable blinker cycle.PNG
* Hex Life Stable blinker cycle.PNG (Filesize: 50.05 KB, Dimensions: 804x717, Views: 185)
« Last Edit: September 25, 2019, 09:12:33 am by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Hexagonal Life
« Reply #1 on: September 25, 2019, 10:01:55 am »
Very fine Bplus!
About rules IMHO you must adapt!  A square has 8 neighbour , an exagon seems to have 6 neighbour so tolerance for life is 2 and overpopulation is  3-6 while solitude is 0-1, bring to life is 2.
Programming isn't difficult, only it's  consuming time and coffee

Offline Jack002

  • Forum Regular
  • Posts: 123
  • Boss, l wanna talk about arrays
    • View Profile
Re: Hexagonal Life
« Reply #2 on: September 25, 2019, 10:13:41 am »
Very cool! now on to 3d hex life, 4d hex life. Really nice job B+
QB64 is the best!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hexagonal Life
« Reply #3 on: September 25, 2019, 03:40:54 pm »
Thanks guys,

TempodiBasic, for me sticking to Conway's rules makes sense, 2 is birth or survival and 3 is survival.
I think I tried 1 for survival as opposed to 3 but that was when I was getting code to run, I will test again.
(A quick check) Oh yeah! looks interesting too, thanks! I will play around with that some more.

Jack002, my backlog of 3D work is #1 Battleship, maybe with Subs... airplanes too?
#2 The thing STxAxTIC suggested, flying through space with orbiting spheres
#3 Hexagon Life... hmm don't hold your breath ;)

PS line 87 is useless as I redraw all cells on each loop, I just noticed it still in there today. It was a carry over from experimenting with code.
« Last Edit: September 25, 2019, 03:50:11 pm by bplus »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Hexagonal Life
« Reply #4 on: September 25, 2019, 03:59:06 pm »
Pretty cool B+, would be a good simulator for a Biology course.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hexagonal Life
« Reply #5 on: September 25, 2019, 06:26:55 pm »
Hi Ken,

I've a feeling that math teachers would be far more receptive to this than biology teachers.

Offline Jack002

  • Forum Regular
  • Posts: 123
  • Boss, l wanna talk about arrays
    • View Profile
Re: Hexagonal Life
« Reply #6 on: September 26, 2019, 11:12:59 am »
This makes me think of the game Othello. There have also been some basic programs that imitate that as well.
QB64 is the best!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hexagonal Life
« Reply #7 on: September 26, 2019, 11:35:32 am »
This makes me think of the game Othello. There have also been some basic programs that imitate that as well.

Othello, not same as Reversi of which I have a copy qbguy's which comes from QB samples according to first line in it. But this version starts with 4 in middle as Othello is supposed to...
Well that is played on square board with square cells moving one piece at a time.

Not like Life "Game" which is not a game in the same sense as these human games with winners and losers and with player skill or luck.

Yeah bplus rather play inhuman games with the gods or aliens take your pick ;-))

Offline Jack002

  • Forum Regular
  • Posts: 123
  • Boss, l wanna talk about arrays
    • View Profile
Re: Hexagonal Life
« Reply #8 on: September 27, 2019, 08:49:36 pm »
I love this game. I keep playing it and playing it. Hex shapes seem more pleasing to the eye than the square ones.
QB64 is the best!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hexagonal Life
« Reply #9 on: September 27, 2019, 10:18:03 pm »
Here is the colorized version using neighbor counts to decide the colors, yellow are neighbor counts of 1 = survival using TempodiBasic rules which are better I think than my first post. White are cells with 2 neighbors = birth or survival.

Turns out I confused Conway's Life rules, there it was 3 neighbors for birth or survival and 2 for survival.

Code: QB64: [Select]
  1. OPTION _EXPLICIT 'Bplus started 2019-09-23 from Hex Minesweeper Custom Field
  2. '2019-09-25 post with original Life Rules
  3. '2019-09-27 OK let's try some more color!
  4.  
  5. DEFINT A-Z
  6. CONST cellR = 10 ' which makes the following constant
  7. CONST xspacing! = 2 * cellR * COS(_D2R(30))
  8. CONST yspacing! = cellR * (1 + SIN(_D2R(30)))
  9.  
  10. TYPE cell
  11.     x AS INTEGER
  12.     y AS INTEGER
  13.     L AS INTEGER
  14. k(0) = &HFF000000: k(1) = &HFFFFFF00: k(2) = &HFFFFFFFF: k(3) = &HFF00BBBB: k(4) = &HFF008800: k(5) = &HFF000066: k(6) = &HFFFF0000
  15. DIM SHARED xmax, ymax, Xarrd, Yarrd 'set all this in customField sub
  16.  
  17.  
  18. '      note: To preserve symmetry when cells hit boundries with a symmetric seed started in middle:
  19. '            y should be odd for 1 cell center x axis, on a shorter inner row
  20. '            If x is odd then one cell is marked in center.
  21. '            If x is even the left one of two center cells will be marked, toggle the one to right also.
  22.  
  23. Xarrd = 41 ' the top left cell has been hacked to duplicate the top right cell, to preserve symmetric seeds through a run
  24.  
  25. Yarrd = 41 'y should always be odd top preserve symmetry of center symmetric seed
  26.  
  27. xmax = (Xarrd + 2) * xspacing!: ymax = (Yarrd + 2) * yspacing!
  28.  
  29. SCREEN _NEWIMAGE(xmax, ymax, 32)
  30. _SCREENMOVE (1280 - xmax) / 2 + 60, (760 - ymax) / 2
  31. DIM SHARED b(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS cell, ng(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS INTEGER 'oversize the board to make it easy to count
  32.  
  33. DIM x, y, xoffset!, xStop, nc, c, r, mb, kh&
  34.  
  35.     _TITLE "Hexagon Life: Left Click to Toggle Cells On/Off, Right Click to Start Run, Escape to Quit"
  36.     ' set x, y for cells and mark ceter cell(s)
  37.     FOR y = 1 TO Yarrd
  38.         IF y MOD 2 = 0 THEN
  39.             xoffset! = .5 * xspacing!: xStop = Xarrd - 1
  40.         ELSE
  41.             xoffset! = 0: xStop = Xarrd
  42.         END IF
  43.         FOR x = 1 TO xStop
  44.             b(x, y).x = x * xspacing! + xoffset! + .5 * xspacing!
  45.             b(x, y).y = y * yspacing! + .5 * yspacing!
  46.             IF x = INT(Xarrd / 2 + .5) AND y = INT(Yarrd / 2 + .5) THEN b(x, y).L = 1 ELSE b(x, y).L = 0 'mark middle cell
  47.             showCell x, y, 7
  48.         NEXT
  49.     NEXT
  50.     _DISPLAY
  51.  
  52.     'setup seed by toggling cells on and off
  53.     WHILE mb <> 2
  54.         kh& = _KEYHIT
  55.         IF kh& = 27 THEN EXIT DO
  56.         mb = 0: c = 0: r = 0
  57.         getCell c, r, mb
  58.         IF mb = 1 THEN
  59.             b(c, r).L = 1 - b(c, r).L
  60.             showCell c, r, 7
  61.         END IF
  62.         _DISPLAY
  63.         _LIMIT 60
  64.     WEND
  65.     mb = 0
  66.     _TITLE "Hexagon Life: Spacebar to Restart/Reseed, Escape to Quit"
  67.     WHILE kh& <> 32 AND kh& <> 27
  68.         kh& = _KEYHIT
  69.         'count the neighbors
  70.         FOR y = 1 TO Yarrd
  71.             IF y MOD 2 = 0 THEN
  72.                 xoffset! = .5 * xspacing!: xStop = Xarrd - 1
  73.             ELSE
  74.                 xoffset! = 0: xStop = Xarrd
  75.             END IF
  76.             FOR x = 1 TO xStop
  77.                 '2 sets of neighbors depending if x offset or not
  78.                 IF xoffset! > .05 THEN
  79.                     nc = b(x, y - 1).L + b(x + 1, y - 1).L + b(x - 1, y).L
  80.                     nc = nc + b(x + 1, y).L + b(x, y + 1).L + b(x + 1, y + 1).L
  81.                 ELSE
  82.                     nc = b(x - 1, y - 1).L + b(x, y - 1).L + b(x - 1, y).L
  83.                     nc = nc + b(x + 1, y).L + b(x - 1, y + 1).L + b(x, y + 1).L
  84.                 END IF
  85.                 'originally tested and posted( 9/25/2019) here only 2 neighbors for birth in Classic Life it takes 3
  86.                 'IF (nc = 3 AND b(x, y).L = 1) OR nc = 2 THEN ng(x, y) = 1 ELSE ng(x, y) = 0
  87.  
  88.                 'TempodiBasic suggested this survival if 1 survival or surviaval and birth for 2 neighbors
  89.                 IF (nc = 1 AND b(x, y).L = 1) OR nc = 2 THEN ng(x, y) = 1 ELSE ng(x, y) = 0
  90.  
  91.                 ' my first test for TempodiBasic, I mistakenly ran this which is good too!
  92.                 'IF (nc = 3 AND b(x, y).L = 1) OR nc = 1 THEN ng(x, y) = 1 ELSE ng(x, y) = 0
  93.  
  94.                 showCell x, y, nc
  95.                 IF x = Xarrd AND y = 1 THEN showCell 1, 1, nc
  96.             NEXT
  97.         NEXT
  98.  
  99.         'redraw all cells so no CLS
  100.         FOR y = 1 TO Yarrd 'transfer data from ng to b().l and show cell
  101.             IF y MOD 2 = 0 THEN
  102.                 xStop = Xarrd - 1
  103.             ELSE
  104.                 xStop = Xarrd
  105.             END IF
  106.             FOR x = 1 TO xStop
  107.                 b(x, y).L = ng(x, y)
  108.                 'showCell x, y
  109.             NEXT
  110.             'fix symmetry for top left corner, match x at other end for bi-lat symmetry
  111.             b(1, 1).L = b(Xarrd, 1).L
  112.             'showCell 1, 1
  113.         NEXT
  114.         _DISPLAY
  115.         _LIMIT 2
  116.     WEND
  117.     IF kh& = 27 THEN EXIT DO
  118.     kh& = 0
  119.  
  120. SUB showCell (c, r, kNum)
  121.     DIM da, x!, y!, lastx!, lasty!, clr AS _UNSIGNED LONG
  122.     IF r MOD 2 = 0 THEN
  123.         IF c < 1 OR c > Xarrd - 1 THEN EXIT SUB
  124.     ELSE
  125.         IF c < 1 OR c > Xarrd THEN EXIT SUB
  126.     END IF
  127.     IF r < 1 OR r > Yarrd THEN EXIT SUB
  128.  
  129.     IF kNum = 7 THEN
  130.         IF b(c, r).L = 1 THEN clr = &HFFFFFFFF ELSE clr = &HFF000000
  131.     ELSE
  132.         clr = k(kNum)
  133.     END IF
  134.     lastx! = b(c, r).x + cellR * COS(_D2R(-30))
  135.     lasty! = b(c, r).y + cellR * SIN(_D2R(-30))
  136.     FOR da = 30 TO 330 STEP 60
  137.         x! = b(c, r).x + cellR * COS(_D2R(da))
  138.         y! = b(c, r).y + cellR * SIN(_D2R(da))
  139.         IF kNum < 7 THEN LINE (lastx!, lasty!)-(x!, y!), clr ELSE LINE (lastx!, lasty!)-(x!, y!), &HFF440044
  140.         lastx! = x!: lasty! = y!
  141.     NEXT
  142.     IF kNum < 7 THEN PAINT (b(c, r).x, b(c, r).y), clr, clr ELSE PAINT (b(c, r).x, b(c, r).y), clr, &HFF440044
  143.  
  144.     'debug
  145.     'cText b(c, r).x, b(c, r).y, 16, &HFF888888, STR$(c) + "," + STR$(r)
  146.  
  147. SUB getCell (returnCol AS INTEGER, returnRow AS INTEGER, mbNum AS INTEGER)
  148.     DIM m, mx, my, mb1, mb2, r, c
  149.     mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  150.     IF mb1 THEN mbNum = 1
  151.     IF mb2 THEN mbNum = 2
  152.     IF mb1 OR mb2 THEN '                      get last place mouse button was down
  153.         WHILE mb1 OR mb2 '                    wait for mouse button release as a "click"
  154.             m = _MOUSEINPUT: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  155.             mx = _MOUSEX: my = _MOUSEY
  156.             'LOCATE 1, 1: PRINT SPACE$(50)
  157.             'LOCATE 1, 1: PRINT mx, my, .5 * xspacing!
  158.             _DISPLAY
  159.         WEND
  160.         FOR r = 1 TO Yarrd
  161.             FOR c = 1 TO Xarrd
  162.                 IF ((mx - b(c, r).x) ^ 2 + (my - b(c, r).y) ^ 2) ^ .5 < .5 * xspacing! THEN
  163.                     returnCol = c: returnRow = r: EXIT SUB
  164.                 END IF
  165.             NEXT
  166.         NEXT
  167.         mbNum = 0 'still here then clicked wrong
  168.     END IF
  169.  
  170. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  171.     DIM a&
  172.     a& = _NEWIMAGE(1, 1, 32)
  173.     _DEST a&
  174.     PSET (0, 0), K
  175.     _DEST 0
  176.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  177.     _FREEIMAGE a& '<<< this is important!
  178.  
  179. 'debug
  180. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  181.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  182.     fg = _DEFAULTCOLOR
  183.     'screen snapshot
  184.     cur& = _DEST
  185.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  186.     _DEST I&
  187.     COLOR K, _RGBA32(0, 0, 0, 0)
  188.     _PRINTSTRING (0, 0), txt$
  189.     mult = textHeight / 16
  190.     xlen = LEN(txt$) * 8 * mult
  191.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  192.     COLOR fg
  193.     _FREEIMAGE I&
  194.  
  195.  

I just watched an episode of Ancient Aliens "The Guardian of the Badlands" jeez these people see faces everywhere and I have been abducted and programmed to share with you this code ;-))

 
Hexagon Life 2.PNG


BTW I have ftri code in to fix the messy lines and paint jobs but haven't gotten to it yet.
« Last Edit: September 27, 2019, 10:24:57 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hexagonal Life
« Reply #10 on: September 28, 2019, 04:26:32 pm »
Cleaned up the Hexagon drawing, changed colors and spent sometime trying to figure out how I seeded the previous screen shot?? stumped on that one!

Code: QB64: [Select]
  1. OPTION _EXPLICIT 'Bplus started 2019-09-23 from Hex Minesweeper Custom Field
  2. '2019-09-25 post with original Life Rules
  3. '2019-09-27 OK let's try some more color!
  4. '2019-09-28 fix hexagon fills by not using PAINT
  5.  
  6. CONST cellR = 10 ' which makes the following constant
  7. CONST xSpacing = 2 * cellR * COS(_D2R(30))
  8. CONST ySpacing = cellR * (1 + SIN(_D2R(30)))
  9.  
  10. TYPE cell
  11.     x AS INTEGER
  12.     y AS INTEGER
  13.     L AS INTEGER
  14. k(0) = &HFF000000: k(1) = &HFFFFFF88: k(2) = &HFFDDDDFF: k(3) = &HFF550033: k(4) = &HFF005500: k(5) = &HFF000044: k(6) = &HFFFF0000
  15. DIM SHARED xmax AS INTEGER, ymax AS INTEGER, Xarrd AS INTEGER, Yarrd AS INTEGER 'set all this in customField sub
  16.  
  17.  
  18. '      note: To preserve symmetry when cells hit boundries with a symmetric seed started in middle:
  19. '            y should be odd for 1 center row
  20. '            x should be equal to or less than y
  21. '            If int(x/2 + .5) is even then the right one of two center cells is marked else the one center cell is marked
  22. '
  23.  
  24. Xarrd = 41 ' the top left cell has been hacked to duplicate the top right cell, to preserve symmetric seeds through a run
  25.  
  26. Yarrd = 41 'y should always be odd top preserve symmetry of center symmetric seed
  27.  
  28. xmax = (Xarrd + 2) * xSpacing: ymax = (Yarrd + 2) * ySpacing
  29.  
  30. SCREEN _NEWIMAGE(xmax, ymax, 32)
  31. _SCREENMOVE (1280 - xmax) / 2 + 60, (760 - ymax) / 2
  32. DIM SHARED b(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS cell, ng(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS INTEGER 'oversize the board to make it easy to count
  33.  
  34. DIM x AS INTEGER, y AS INTEGER, xoffset, xStop AS INTEGER, nc AS INTEGER, c AS INTEGER, r AS INTEGER, mb AS INTEGER, kh&
  35.  
  36.     _TITLE "Hexagon Life: Left Click to Toggle Cells On/Off, Right Click to Start Run, Escape to Quit"
  37.     ' set x, y for cells and mark ceter cell(s)
  38.     FOR y = 1 TO Yarrd
  39.         IF y MOD 2 = 0 THEN
  40.             xoffset = .5 * xSpacing: xStop = Xarrd - 1
  41.         ELSE
  42.             xoffset = 0: xStop = Xarrd
  43.         END IF
  44.         FOR x = 1 TO xStop
  45.             b(x, y).x = x * xSpacing + xoffset + .5 * xSpacing
  46.             b(x, y).y = y * ySpacing + .5 * ySpacing
  47.             IF x = INT(Xarrd / 2 + .5) AND y = INT(Yarrd / 2 + .5) THEN b(x, y).L = 1 ELSE b(x, y).L = 0 'mark middle cell
  48.             showCell x, y, 7
  49.         NEXT
  50.     NEXT
  51.     _DISPLAY
  52.  
  53.     'setup seed by toggling cells on and off
  54.     WHILE mb <> 2
  55.         kh& = _KEYHIT
  56.         IF kh& = 27 THEN EXIT DO
  57.         mb = 0: c = 0: r = 0
  58.         getCell c, r, mb
  59.         IF mb = 1 THEN
  60.             b(c, r).L = 1 - b(c, r).L
  61.             showCell c, r, 7
  62.         END IF
  63.         _DISPLAY
  64.         _LIMIT 60
  65.     WEND
  66.     mb = 0
  67.     _TITLE "Hexagon Life: Spacebar to Restart/Reseed, Escape to Quit"
  68.     WHILE kh& <> 32 AND kh& <> 27
  69.         kh& = _KEYHIT
  70.         'count the neighbors
  71.         FOR y = 1 TO Yarrd
  72.             IF y MOD 2 = 0 THEN
  73.                 xoffset = .5 * xSpacing: xStop = Xarrd - 1
  74.             ELSE
  75.                 xoffset = 0: xStop = Xarrd
  76.             END IF
  77.             FOR x = 1 TO xStop
  78.                 '2 sets of neighbors depending if x offset or not
  79.                 IF xoffset > .05 THEN
  80.                     nc = b(x, y - 1).L + b(x + 1, y - 1).L + b(x - 1, y).L
  81.                     nc = nc + b(x + 1, y).L + b(x, y + 1).L + b(x + 1, y + 1).L
  82.                 ELSE
  83.                     nc = b(x - 1, y - 1).L + b(x, y - 1).L + b(x - 1, y).L
  84.                     nc = nc + b(x + 1, y).L + b(x - 1, y + 1).L + b(x, y + 1).L
  85.                 END IF
  86.                 'originally tested and posted( 9/25/2019) here only 2 neighbors for birth in Classic Life it takes 3
  87.                 'IF (nc = 3 AND b(x, y).L = 1) OR nc = 2 THEN ng(x, y) = 1 ELSE ng(x, y) = 0
  88.  
  89.                 'TempodiBasic suggested this survival if 1 survival or surviaval and birth for 2 neighbors
  90.                 IF (nc = 1 AND b(x, y).L = 1) OR nc = 2 THEN ng(x, y) = 1 ELSE ng(x, y) = 0
  91.  
  92.                 ' my first test for TempodiBasic, I mistakenly ran this which is good too!
  93.                 'IF (nc = 3 AND b(x, y).L = 1) OR nc = 1 THEN ng(x, y) = 1 ELSE ng(x, y) = 0
  94.  
  95.                 showCell x, y, nc
  96.                 IF x = Xarrd AND y = 1 THEN showCell 1, 1, nc
  97.             NEXT
  98.         NEXT
  99.  
  100.         'redraw all cells so no CLS
  101.         FOR y = 1 TO Yarrd 'transfer data from ng to b().l and show cell
  102.             IF y MOD 2 = 0 THEN
  103.                 xStop = Xarrd - 1
  104.             ELSE
  105.                 xStop = Xarrd
  106.             END IF
  107.             FOR x = 1 TO xStop
  108.                 b(x, y).L = ng(x, y)
  109.                 'showCell x, y
  110.             NEXT
  111.             'fix symmetry for top left corner, match x at other end for bi-lat symmetry
  112.             b(1, 1).L = b(Xarrd, 1).L
  113.             'showCell 1, 1
  114.         NEXT
  115.         _DISPLAY
  116.         _LIMIT 1
  117.     WEND
  118.     IF kh& = 27 THEN EXIT DO
  119.     kh& = 0
  120.  
  121. SUB showCell (c AS INTEGER, r AS INTEGER, kNum AS INTEGER)
  122.     DIM clr AS _UNSIGNED LONG
  123.     IF r MOD 2 = 0 THEN
  124.         IF c < 1 OR c > Xarrd - 1 THEN EXIT SUB
  125.     ELSE
  126.         IF c < 1 OR c > Xarrd THEN EXIT SUB
  127.     END IF
  128.     IF r < 1 OR r > Yarrd THEN EXIT SUB
  129.     IF kNum = 7 THEN
  130.         IF b(c, r).L = 1 THEN clr = &HFFFFFFFF ELSE clr = &HFF000000
  131.     ELSE
  132.         clr = k(kNum)
  133.     END IF
  134.     IF kNum < 7 THEN
  135.         fHexH b(c, r).x, b(c, r).y, cellR, clr
  136.         hexH b(c, r).x, b(c, r).y, cellR, &HFF000000
  137.     ELSE
  138.         fHexH b(c, r).x, b(c, r).y, cellR, clr
  139.         hexH b(c, r).x, b(c, r).y, cellR, &HFF440044
  140.     END IF
  141.  
  142. SUB getCell (returnCol AS INTEGER, returnRow AS INTEGER, mbNum AS INTEGER)
  143.     DIM m, mx, my, mb1, mb2, r AS INTEGER, c AS INTEGER
  144.     mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  145.     IF mb1 THEN mbNum = 1
  146.     IF mb2 THEN mbNum = 2
  147.     IF mb1 OR mb2 THEN '                      get last place mouse button was down
  148.         WHILE mb1 OR mb2 '                    wait for mouse button release as a "click"
  149.             m = _MOUSEINPUT: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  150.             mx = _MOUSEX: my = _MOUSEY
  151.             'LOCATE 1, 1: PRINT SPACE$(50)
  152.             'LOCATE 1, 1: PRINT mx, my, .5 * xSpacing
  153.             _DISPLAY
  154.         WEND
  155.         FOR r = 1 TO Yarrd
  156.             FOR c = 1 TO Xarrd
  157.                 IF ((mx - b(c, r).x) ^ 2 + (my - b(c, r).y) ^ 2) ^ .5 < .5 * xSpacing THEN
  158.                     'LOCATE 1, 1: PRINT SPACE$(50)
  159.                     'LOCATE 1, 1: PRINT c, r
  160.                     returnCol = c: returnRow = r: EXIT SUB
  161.                 END IF
  162.             NEXT
  163.         NEXT
  164.         mbNum = 0 'still here then clicked wrong
  165.     END IF
  166.  
  167. 'draw Hexagon Outline that can be packed Horizontally, flat edge to flat edge
  168. SUB hexH (xOrigin AS SINGLE, yOrigin AS SINGLE, radius AS SINGLE, c AS _UNSIGNED LONG)
  169.     DIM polyAngle AS SINGLE, aOff AS SINGLE, x1 AS SINGLE, y1 AS SINGLE, i AS INTEGER, x2 AS SINGLE, y2 AS SINGLE
  170.     polyAngle = _PI(2) / 6: aOff = _PI / 2
  171.     x1 = xOrigin + radius * COS(polyAngle + aOff)
  172.     y1 = yOrigin + radius * SIN(polyAngle + aOff)
  173.     FOR i = 2 TO 7
  174.         x2 = xOrigin + radius * COS(i * polyAngle + aOff)
  175.         y2 = yOrigin + radius * SIN(i * polyAngle + aOff)
  176.         LINE (x1, y1)-(x2, y2), c
  177.         x1 = x2: y1 = y2
  178.     NEXT
  179.  
  180. 'draw filled Hexagon that can be packed Horizontally, flat edge to flat edge
  181. 'uses SUB fTri
  182. SUB fHexH (xOrigin AS SINGLE, yOrigin AS SINGLE, radius AS SINGLE, c AS _UNSIGNED LONG)
  183.     DIM polyAngle AS SINGLE, aOff AS SINGLE, x1 AS SINGLE, y1 AS SINGLE, i AS INTEGER, x2 AS SINGLE, y2 AS SINGLE
  184.     polyAngle = _PI(2) / 6: aOff = _PI / 2
  185.     x1 = xOrigin + radius * COS(polyAngle + aOff)
  186.     y1 = yOrigin + radius * SIN(polyAngle + aOff)
  187.     FOR i = 2 TO 7
  188.         x2 = xOrigin + radius * COS(i * polyAngle + aOff)
  189.         y2 = yOrigin + radius * SIN(i * polyAngle + aOff)
  190.         fTri xOrigin, yOrigin, x1, y1, x2, y2, c
  191.         x1 = x2: y1 = y2
  192.     NEXT
  193.  
  194. SUB fTri (x1 AS SINGLE, y1 AS SINGLE, x2 AS SINGLE, y2 AS SINGLE, x3 AS SINGLE, y3 AS SINGLE, K AS _UNSIGNED LONG)
  195.     DIM a&
  196.     a& = _NEWIMAGE(1, 1, 32)
  197.     _DEST a&
  198.     PSET (0, 0), K
  199.     _DEST 0
  200.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  201.     _FREEIMAGE a& '<<< this is important!
  202.  
  203.  
Hex Life 2 fix.PNG

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Hexagonal Life
« Reply #11 on: September 29, 2019, 03:18:50 pm »
Hi Bplus I think that both the model with original rules both that you have coded following my suggestion suffer of overpopulation!

However I find 2 seed for the same permanent entity!

 
Hexagonal seed.jpg
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hexagonal Life
« Reply #12 on: September 30, 2019, 11:03:07 am »
Yeah, I don't know how well explored Hexagon Life is compared to Classic Conway Life action at the boundary lines is not as neat as with Classic because of 6 way symmetry versus 4 way of Classic so maybe the playing field needs to be hexagonal also? How about Hexagonal arrays to hold the data also!?!

But you might run into some of the same problems if the square or rectangular cells were stagger-stacked like bricks.

I wonder if there exist a set of rules for Hexagonal Life that would yield the equivalent of a glider gun or something equally as amazing. I have noticed that stable blinkers usually cycle in multiples of 3, like the one TempodiBasic is showing.
« Last Edit: September 30, 2019, 11:04:35 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hexagonal Life
« Reply #13 on: September 30, 2019, 12:00:18 pm »
Face maker seeds,

Face maker seed.PNG
* Face maker seed.PNG (Filesize: 2.94 KB, Dimensions: 159x146, Views: 155)

* Face maker 2.PNG (Filesize: 2.55 KB, Dimensions: 145x136, Views: 276)
Darth Vader seed.PNG
* Darth Vader seed.PNG (Filesize: 2.84 KB, Dimensions: 152x157, Views: 169)
Face 2.PNG
* Face 2.PNG (Filesize: 36.01 KB, Dimensions: 749x676, Views: 192)

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Hexagonal Life
« Reply #14 on: September 30, 2019, 03:33:30 pm »
LOL this one is much better! After around 30 seconds or so it filled the entire screen. :) You also might want to add in the _TITLE "Generations: "+g  where g is how many times they multiply. Really cool. Or you can use a different word than Generations.