Hello there!

I would like to introduce to you Calcular Automation, a multi-state cellular automation simulator written in assembly for the TI-84+ CE. It supports nearly any fully symmetrical 2-state, 3-state, or 4-state rule, including Conway's Game of Life (AKA Life), Wireworld, Brian's Brain, Star Wars, Day and Night, and many more. Here's the progress so far:

Completed:
☑ Simulation, editor, zoom in/out
☑ Multiple rules (temporary implementation)

Plans:
☐ Disable extra cell states for 2-state and 3-state rules
☑ Help screen
☐ Configurable grid (width, height, edges loop on/off)
☐ Configurable rules
☐ Configurable colors
☐ Saving grid in appvar
☐ Saving favorite rules

Tentative Plans:
☐ FPS counter?
☐ Different control scheme?
☐ Support for elementary (1D) cellular automata?
☐ More optimizations? (Please give suggestions!)

The current controls are as follows:
• Arrow keys - Move cursor
• 2nd/Comma - Toggle 1st cell state
• Left Parenthesis - Toggle 2nd cell state
• Right Parenthesis - Toggle 3rd cell state
• 0/1/2/3 - Set to cell state n
• Alpha - Simulate one generation
• Math - Quick simulation (press any key to stop)
• Del - Reset world
• Mode/Clear - Exit
• F1 - Use rule "Life"
• F2 - Open help
• F3 - Use rule "Wireworld"
• F4 - Use rule "Brian's Brain"
• F5 - Use rule "Star Wars"

The source code is a bit of a mess, but I'll throw it in there anyway if you want to mess with the settings. (To add you own rules, modify the Rule_Name and EndCell_Data in Conway.asm and the colors at the end of routines/gfx.asm. Have fun!)

> Download <

Changelog:

v2.01
* Optimized the code a bit
* Reorganized the file structure
* F2 now opens the help screen

v2.00
* ~90% of code rewritten
* Status bar displays cursor position, generation/population counts, zooming/scrolling
* Support for up to 4-state cellular automata

v1.00
* Initial release (supports Conway's Life on a fixed grid size)
Thank you Ivoah, MateoConLechuga and KermPhD! I have gotten rid of that nasty battery by disabling interrupts with "di" at the start and "ei" before exiting.

EDIT: Not working anymore. Sad

EDIT2: Got rid of _GetKey, now solved again! Very Happy
Great work on this! I'm pleased to see that there are others willing to take the time to learn assembly. Smile It's a beast of a language the farther down the road you go. If you need any assistance with any of your points, feel free to ask away! Also, if you like some help optimizing your code, or just some feedback, that is what we are all here for Smile Good luck!
While browsing the Google Play for cellular automaton I found this awesome app:
"Instinct - Cellular Automaton"
Having this one "ported" (cloned) on-calc would be really nice!

It has basically a main menu, which let's you either select sandbox mode or tutorial mode.
When selecting the tutorial mode, you are prompted to choose a rule and then you go through at tutorial where you build and define the world and rules by yourself. When selecting sandbox mode, you are allowed to select and build whatever rules you want - making an infinite range of possibilities.
The main advantage is that the user does not need to have predefined rules but he can defune whatever he wants to try out. But if he finds that toi complicated, there is a set of rules already there to teach him make his own Smile.
Thank you! I will definitely have a look at that! Normally I use a program called Golly, which also allows you to define your own rules, board size, edges behavior, colors, etc. Golly runs EXTREMELY fast but (unlike the app you mentioned) has somewhat of a learning curve.

EDIT: I think the first step towards building something like Instinct would be a custom font + main menu. A resizable board would ridiculously hard, as would zooming in and out and scrolling. But as I mentioned in the OP, I do want to add things like edges and rule customization. (Predefined rules at the very least, preferably custom rules defined by the user)

ANOTHER EDIT: IDEA! For customization of complicated annoying stuff like colors, the program could actually change its own code in the RAM by modifying the byte or whatever where the color is used in the program! I have no idea how to do this but I imagine it would be very possible and probably the fastest way to accomplish this (rather than referencing RAM each time to get what would normally be a hard-coded color).

Nik wrote:
While browsing the Google Play for cellular automaton I found this awesome app:
"Instinct - Cellular Automaton"
Having this one "ported" (cloned) on-calc would be really nice!

It has basically a main menu, which let's you either select sandbox mode or tutorial mode.
When selecting the tutorial mode, you are prompted to choose a rule and then you go through at tutorial where you build and define the world and rules by yourself. When selecting sandbox mode, you are allowed to select and build whatever rules you want - making an infinite range of possibilities.
The main advantage is that the user does not need to have predefined rules but he can defune whatever he wants to try out. But if he finds that toi complicated, there is a set of rules already there to teach him make his own Smile.
I am looking forward to see this progress, but unfortunately I do not own a color calculator, so I won't be able to try this out...
A possibly worthy source of inspiration for features is François Leiber's excellent implementation of the Game of Life for the TI-68k/AMS series, http://leiber.free.fr/ti/vie/index.html / http://www.ticalc.org/archives/files/fileinfo/336/33618.html . There's an English version.
It supports lots of rules other than the classic 23/3, complete with explanations (both calculator-side and computer-side). And it's FLOSS (GPLv2) Smile
Lionel Debroux wrote:
A possibly worthy source of inspiration for features is François Leiber's excellent implementation of the Game of Life for the TI-68k/AMS series, http://leiber.free.fr/ti/vie/index.html / http://www.ticalc.org/archives/files/fileinfo/336/33618.html . There's an English version.
It supports lots of rules other than the classic 23/3, complete with explanations (both calculator-side and computer-side). And it's FLOSS (GPLv2) Smile


I just pulled that up on one of those old TI-Emulators and wow is it polished! If I could get my program to that level of quality I would be so thrilled.
I am having the stupidest problem... So I am trying to semi-rewrite the code so that the indices go from, for example, 1-40 instead of 0-39. The problem is I keep getting a "RAM Cleared" error on this one line:
Code:
ld (hl),a
HL should be pointing to a byte in which a semi-temporary array contains the amount of neighboring live cells per cell (so one byte per cell).

EDIT: Here's a link to the code (new and old): https://dl.dropboxusercontent.com/u/24594573/Calculator/Debug/Conway%20RAM%20CLEARED%2010-4-15.zip
Hactar wrote:
I am having the stupidest problem... So I am trying to semi-rewrite the code so that the indices go from, for example, 1-40 instead of 0-39. The problem is I keep getting a "RAM Cleared" error on this one line:
Code:
ld (hl),a
HL should be pointing to a byte in which a semi-temporary array contains the amount of neighboring live cells per cell (so one byte per cell).

EDIT: Here's a link to the code (new and old): https://dl.dropboxusercontent.com/u/24594573/Calculator/Debug/Conway%20RAM%20CLEARED%2010-4-15.zip

I believe the issue is that it it is loading 24 bit rather than 16. So, if you have something like this:


Code:
 ld h,0
 ld l,c

It needs to be:

Code:
 ld hl,0
 ld l,c

Or a more optimized version:

Code:
 or a,a \ sbc hl,hl
 ld l,c


The same goes for this:

Code:
 ld d,0
 ld e,b


All 16 bit z80 registers are 24bit on the ez80 in ADL mode Smile
And another problem. Sad This time nothing is happening when I press "Y=" to simulate one generation. It is definitely not a rendering problem... and the code should work the same as my unoptimized version... I don't know. The error is probably either in "SpreadToAdj" (or some lower-level label it uses) or "ConwayLogic" (or some lower-level label it uses) Here's the code: https://dl.dropboxusercontent.com/u/24594573/Calculator/Debug/Conway%20not%20rendering%2010-4-15.zip I have to leave for the night; see you all tomorrow!

AARRRGG I think I found the problem. Notice anything about the "ConwayCell" label? https://dl.dropboxusercontent.com/u/24594573/Calculator/Debug/ConwayCell.png
Okay, so I am going to switch to 8bpp mode, because I don't need 65.5 thousand different colors able to be displayed. (Who does?) How exactly do I do that? I found this code:

Code:
setup8bppMode:
   ld a,lcdBpp8
   ld (mpLcdCtrl),a
   ld hl,images_paletteStart
   ld de,mpLcdPalette
   ld bc,images_paletteEnd-images_paletteStart
   ldir
   ret

But apparently I need an color palette or something? Help would be much appreciated.

EDIT: Also, will the OS automatically switch back to 16bpp mode when my program exits? Or do I have to do that manually?
Use this to setup 8bpp mode:

Code:
ld a,lcdBpp8
ld (mpLcdCtrl),a


Use this to set up the palette:

Code:
set1555Palette:
   ld hl,mpLcdPalette             ; palette mem
   ld b,0
_cp1555loop:
   ld d,b
   ld a,b
   and %11000000
   srl d
   rra
   ld e,a
   ld a,%00011111
   and b
   or e
   ld (hl),a
   inc hl
   ld (hl),d
   inc hl
   inc b
   jr nz,_cp1555loop
   ret


And use this to go back to 16bpp mode when you exit your program:

Code:
ld a,lcdBpp16
ld (mpLcdCtrl),a


Now, you can write directly to the LCD. Here is the color table for this mode, if you follow these routines:
Hactar wrote:
AARRRGG I think I found the problem. Notice anything about the "ConwayCell" label? https://dl.dropboxusercontent.com/u/24594573/Calculator/Debug/ConwayCell.png
Heh, i've had way too many of those mistakes, debugging for hours to find out that it was something silly like that preventing things from working. Regarding or a / sbc hl,hl, if you are sure that the carry flag will be reset before that you can leave out the 'or a'. And in the image you posted, i see:

Code:
ld a,(hl)
inc a
ld (hl),a
Why not do:

Code:
inc (hl)
?

You've probably changed that code by now, but in ConwayCell, you'll never reach the 'jp nc,CellOff' statement (line 73), since z is either set or reset, so it either jumps to DrawCell or CellOn.

Also, i'm not sure if you figured out the interrupts issue, the problem may well be (or have been) that you used a system routine which re-enabled interrupts, so interrupts got turned back on mid-program.

You say you just started learning asm, i'm really impressed with all the progress you've made! Keep it up!
chickendude wrote:
And in the image you posted, i see:

Code:
ld a,(hl)
inc a
ld (hl),a
Why not do:

Code:
inc (hl)
?

Thanks, fixed. Wink I didn't realize I could directly increment a memory location, but that is awesome!

chickendude wrote:
You've probably changed that code by now, but in ConwayCell, you'll never reach the 'jp nc,CellOff' statement (line 73), since z is either set or reset, so it either jumps to DrawCell or CellOn.

Yes, that was just for debugging purposes (to see if it was even reaching ConwayCell at all). It is changed now.

chickendude wrote:
Also, i'm not sure if you figured out the interrupts issue, the problem may well be (or have been) that you used a system routine which re-enabled interrupts, so interrupts got turned back on mid-program.

Yes, I was using _GetKey, which must have been causing those issues. For now I am using _GetCSC, though I plan to try to implement some direct input method at some point in the near future.

But now I have another problem. :/ I am trying to load a (for now) hard-coded "board" into the program. Basically, I have a label with a giant block of binary for each cell (1=on, 0=off). Basically it has a hard-coded loop for each bit of the data, and a "dec bc / jp nz,LoopLabel"-type loop for every eight cells. Here's the code: http://pastebin.com/XzhA7tQr http://pastebin.com/18pguCJY
Rather than this:

Code:
LdBoard:
        ; DE = mem loc of board to load
        ; DE and HL are sorta switched; DE is the source and HL is the destination
        ld hl,Board
        ld bc,BoardSize/8
LdBoard_Loop:
        push bc
        ld a,(de)
        bit 0,a
        call z,LdBoard_On
        inc hl
        bit 1,a
        call z,LdBoard_On
        inc hl
        bit 2,a
        call z,LdBoard_On
        inc hl
        bit 3,a
        call z,LdBoard_On
        inc hl
        bit 4,a
        call z,LdBoard_On
        inc hl
        bit 5,a
        call z,LdBoard_On
        inc hl
        bit 6,a
        call z,LdBoard_On
        inc hl
        bit 7,a
        call z,LdBoard_On
        inc hl
        inc de
        pop bc
        dec bc
        jp nz,LdBoard_Loop
        jp RenderBoard
LdBoard_On:
        ld (hl),OnCellData
        ret
LdBoard_Off:
        ld (hl),OffCellData
        ret


Do this:

Code:
LdBoard:
 ld hl,Board
 ld bc,BoardSize/8
LdBoard_Loop:
 ld a,(de)
 push bc
  ld b,8
smallLoop:
  ld (hl),OffCellData
  rla \ jr nc,CellOff
  ld (hl),OnCellData
CellOff:
  inc hl
  djnz smallLoop
 pop bc
 inc de
 dec bc
 ld a,b
 or a,c
 jp nz,LdBoard_Loop
 jp RenderBoard


The rla instructions rotates the bit left, and copies the leaving 7th bit to the carry flag, where the jr nc instruction uses it to tell if a bit is on or off. It loops 8 times for each but in the byte. This is generally a good compression technique, at least for now Smile


Code:
 dec bc
 jp nz,LdBoard_Loop

Doesn't work like you think it might. You need to do this instead:

Code:
 dec bc
 ld a,b
 or a,c
 jp nz,LdBoard_Loop


Hope this helps! Smile
Thank you very much, the program is now working! Very Happy I have an idea for a more efficient way to save the state of a board in an AppVar. (I'm talking general CA, not just Conway. This is especially good for Wireworld.) There will first be a block of data, where each bit is a zero for blank, and a one for any other state. Then after that block, there will be a string of bytes defining the states of the blocks that are not off. So here's what the processor would do:

Code:

For i = 1, BoardSize
    Read the next bit of the first block.
    If bit is 0, CellOff
    If bit is 1, Then
        Read the next byte of the second block
        Load that value into the current cell's state
    End
End


If only ASM were as easy as pseudo-code. *sigh*
Whoa, this is neat! Wish I had a CE to test it out.
Allow me to offer my thoughts and a timeline of sorts on adding rules, although it's not immediately relevant to the coding discussion and may not be ever implemented - since HighLife and WireWorld are two very different beasts.

- Two-state (on or off/binary) rules should come first. Totalistic rules (where the cell's transition depends on the number of neighbors, not their position - these are represented in B/S notation) would probably be the easiest to accomodate, although B0 rules would be tricky (a cell is born if it has zero neighbors, causing a theoretically infinite expanse of live cells, and a really ugly-looking strobing effect from generation to generation if the rule also lacks survival on 8 neighbors) - Golly handles these by alternating the rule every generation. More here.

- After that's taken care of, you could experiment with allowing non-totalistic rules - there are multiple notations, but I think the one linked is the easiest to understand (note that, in the chart, the colored cells are the relevant ones, not the black cells. That tripped me up at first.)

- [EDIT: This is basically what Mateo describes in the post directly below this one, but the extra colors/states don't act as live cells] The Generations algorithm should come next, since it's sort of the 'next step up' from two-state CAs. You probably won't have to allow for 255 cell states like Golly does, though - there are some exceptions, but for the most part a rule stops changing once you add more than 10 extra states to it.

- There are a few ways you could go from there - WireWorld might be easy to implement after adding Generations rules, since it's essentially the Generations rule /12/3 but with restrictions on where cells can be born. Or you might want to go all-out and add support for some sort of ruletable (Golly's algorithm is described here, although the format would have to be changed a lot because it's on a calculator and all); I don't think that would be the best idea, though.

That's about it. I know it's sort of unsolicited advice, and I'm not saying you should do everything I've listed - I just think it's the best course of action if you decide to. This is a really cool project, and I'm definitely going to be following its progress in the future!
I would think it would be quite cool to see different colors for time spent in a state. If a cell remains on, simply change the color to something else. If a new cell is created, initialize it to a starting color. Best of luck! Smile
I did a complete rewrite of most of the code and added lots of new features, some of which are not accessible except in the source code because I haven't added the user interface for them yet. Calcular Automation now also supports multi-state automata! See the changelog for more details.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement