I've recently started learning AXE, and the first program I'm working on is a simple implementation of Conway's Game of Life that takes input from the graph screen, and I have a question about optimizing it.
Forgive me if the question demonstrates a profound lack of understanding of the language, but hey, that's why I'm asking it.

Currently it uses the main buffer to hold the current generation, back buffer for calculating the next generation, one labeled GDB1 for the cells that changed last generation, and GDB2, which is GDB1 with all neighbor cells turned on (Used so that the main algorithm checks only the cells and the neighbors of cells that changed last generation.)

I thought of a way I could possibly optimize the routine for copying GDB1 to GDB2 and filling in neighboring cells.
Code as it currently is:

:ClrDraw(GDB2)
:Copy(GDB1,GDB2)
:For(K,1,92
:For(L,1,61
:If pxl-Test(K,L,GDB1)
:Pxl-On(K-1,L-1,GDB2
:Pxl-On(K-1,L,GDB2
:Pxl-On(K-1,L+1,GDB2
:Pxl-On(K,L-1,GDB2
:Pxl-On(K,L+1,GDB2
:Pxl-On(K+1,L-1,GDB2
:Pxl-On(K+1,L,GDB2
:Pxl-On(K+1,L+1,GDB2
:End:End:End

If I could use the Horizontal+-/Vertical+- commands to get a buffer of GDB1 shifted one direction over then combine it into GDB2, then keep moving GDB1 around until all 8 neighbor cells are filled, I'm pretty sure it'd be a whole lot faster than using 8 Pxl-Ons for all 5460 coordinates. To do this, I'd need a way to only copy the on pixels between buffers rather than overwriting the buffer entirely, like how RecallPic works in TI-BASIC.

If I had a solid understanding of how the buffers are represented in memory, this might be fairly trivial, but I'm still figuring all that out. Until then, does anyone have an idea for how I would accomplish this in a way that will improve performance compared to the current routine?


Here's the full code for anyone who's interested:

:.GAMOLIF
:Full
:DiagnosticOff
:ClrDraw^^r
:ClrDraw(GDB1)
:ClrDraw(GDB2)
:Buff(768)->GDB1
:Buff(768)->GDB2
:
:For(A,1,92
:For(B,1,61
:If pxl-Test(A,B
:Pxl-On(A,B,GDB1
:Pxl-On(A,B)^^r
:End:End:End
:
:
:While getKey!=15
:DispGraph
:ClrDraw(GDB2)
:Copy(GDB1,GDB2
:For(K,1,92)
:For(L,1,61)
:If pxl-Test(K,L,GDB1)
:Pxl-On(K-1,L-1,GDB2
:Pxl-On(K-1,L,GDB2
:Pxl-On(K-1,L+1,GDB2
:Pxl-On(K,L-1,GDB2
:Pxl-On(K,L+1,GDB2
:Pxl-On(K+1,L-1,GDB2
:Pxl-On(K+1,L,GDB2
:Pxl-On(K+1,L+1,GDB2
:End:End:End
:
:ClrDraw(GDB1)
:For(K,1,92
:For(L,1,61
:If pxl-Test(K,L,GDB2
:pxl-Test(K-1,L-1)+pxl-Test(K-1,L)+pxl-Test(K-1,L+1)+pxl-Test(K,L-1)+pxl-Test(K,L+1)+pxl-Test(K+1,L-1)+pxl-Test(K+1,L)+pxl-Test(K+1,L+1)->M
:If M=3 or (M=2 and pxl-Test(K,L
:Pxl-On(K,L)^^r
:Else
:Pxl-Off(K,L)^^r
:End
:
:If pxl-Test(K,L)!=pxl-Test(K,L)^^r
:Pxl-On(K,L,GDB1
:End
:End
:
:End:End
:RecallPic
:End
:Return


[/code]
br0f7401 wrote:
Currently it uses the main buffer to hold the current generation, back buffer for calculating the next generation, one labeled GDB1 for the cells that changed last generation, and GDB2, which is GDB1 with all neighbor cells turned on (Used so that the main algorithm checks only the cells and the neighbors of cells that changed last generation.)

You can't define the main buffer to be GDB1. GDB1 is only used for a new pointer to be defined. At least I have never gotten L6->GDB1 to work. For drawing to the main buffer, use L6 for the pointer and for the back buffer, use L3. I'm just going to address the statements as main and back buffer for easier clarification.

br0f7401 wrote:
I thought of a way I could possibly optimize the routine for copying GDB1 to GDB2 and filling in neighboring cells.
Code as it currently is:

Code:
:ClrDraw(GDB2)
:Copy(GDB1,GDB2)
:For(K,1,92
:For(L,1,61
:If pxl-Test(K,L,GDB1)
:Pxl-On(K-1,L-1,GDB2
:Pxl-On(K-1,L,GDB2
:Pxl-On(K-1,L+1,GDB2
:Pxl-On(K,L-1,GDB2
:Pxl-On(K,L+1,GDB2
:Pxl-On(K+1,L-1,GDB2
:Pxl-On(K+1,L,GDB2
:Pxl-On(K+1,L+1,GDB2
:End:End:End


I don't recommend stacking the Ends together like that. It just makes the code harder to read with multiple for( and if's.
Now for the actual code, in the first line, you cleared the back buffer, then copied main buffer to back. This code can be shortened to:

Code:
RecallPic

This will basically just copy the back buffer directly to the main buffer. Clearing the back buffer first wouldn't change anything if you're overriding it with the main buffer right after.

br0f7401 wrote:
If I could use the Horizontal+-/Vertical+- commands to get a buffer of GDB1 shifted one direction over then combine it into GDB2, then keep moving GDB1 around until all 8 neighbor cells are filled, I'm pretty sure it'd be a whole lot faster than using 8 Pxl-Ons for all 5460 coordinates. To do this, I'd need a way to only copy the on pixels between buffers rather than overwriting the buffer entirely, like how RecallPic works in TI-BASIC.

I don't know if this would do anything? Confused

Here is an example code that basically does what you want it to do, except for the starting where you check if the pixel is on and color in the starting dots. Mine just makes random pixels everywhere. I also made it fit in a smaller area. That should be easy to change though:

Code:
.CGOF
Full
ClrDraw
For(Y,8,55)
 For(X,1,10)
  rand->{Y*12+X+L6}
 End
End
.Draws random pixels in the area for CGOF, can be replaced with whatever is on the screen, but a blank screen will remain blank
StorePicDispGraph
.Copies main buffer to back buffer, displays main buffer
Repeat getKey(15)
 For(Y,8,55)
  For(X,8,87)
   .Loops through the screen area that you would want to test pxls for
   pxl-Test(X-1,Y-1)+pxl-Test(X,Y-1)+pxl-Test(X+1,Y-1)+pxl-Test(X-1,Y)+pxl-Test(X+1,Y)+pxl-Test(X-1,Y+1)+pxl-Test(X,Y+1)+pxl-Test(X+1,Y+1)->A
   .This parts adds up the pxls around the pxl you are testing, what CGOF is based on
   If pxl-Test(X,Y)
    !If A=2 or (A=3)
     .If live pxl is not surrounded by 2 or 3 pxls
     Pxl-Off(X,Y)^^r
    End
   Else
    If A=3
     .If dead pxl is surrounded by 3 pxls
     Pxl-On(X,Y)^^r
    End
   End
  End
 End
 RecallPicDispGraph
 .Copies back buffer, which has the pxl changes, like yours had before, and displays that afterwards
End
Return

I don't know anything about optimizing CGOF, but you can use this code to learn a lot about Axe and optimizations. There are some parts that I chose to unoptimize back for readability, so if you want to full code, just ask.
Haobo wrote:

You can't define the main buffer to be GDB1. GDB1 is only used for a new pointer to be defined. At least I have never gotten L6->GDB1 to work. For drawing to the main buffer, use L6 for the pointer and for the back buffer, use L3. I'm just going to address the statements as main and back buffer for easier clarification.


I was unclear about what buffers I was using, sorry. I'm actually using four different buffers, L6, L3, GDB1, and GDB2. GDB1 contains pixels that changed between the last generation and the current, and GDB2 is GDB1 with all of its neighbor cells filled in.

Before the bit of code where all the neighbors of a cell are added up, there's a conditional for whether the cell is on in GDB2, and if it isn't, it won't run. This means that time isn't wasted on checking the neighbors of large dead portions of the screen, or still lifes.

All I want to know is if there's a fast method of copying the on pixels of a buffer to another buffer without overwriting the original buffer entirely. I don't know if it will actually make my code faster, but I'd like to try it.
I tried something else for optimization and here's the code I have now:

.GAMOLIF
Full
Full^^r
#ExprOn
DiagnosticOff
ClrDraw^^r
ClrDraw(GDB1)
ClrDraw(GDB2)
Buff(768)->GDB1
Buff(768)->GDB2

For(A,1,92
For(B,1,61
If pxl-Test(A,B
Rect(A-1,B-1,3,3,GDB1
Pxl-On(A,B)^^r
End:End:End


Repeat getKey(15)

RecallPicDispGraph
Copy(GDB1,GDB2)
ClrDraw(GDB1)
For(K,1,92
For(L,1,61
If pxl-Test(K,L,GDB2
pxl-Test(K-1,L-1)+pxl-Test(K-1,L)+pxl-Test(K-1,L+1)+pxl-Test(K,L-1)+pxl-Test(K,L+1)+pxl-Test(K+1,L-1)+pxl-Test(K+1,L)+pxl-Test(K+1,L+1)->M
If M=3 or (M=2 and pxl-Test(K,L
Pxl-On(K,L)^^r
Else
Pxl-Off(K,L)^^r
End

If pxl-Test(K,L)!=pxl-Test(K,L)^^r
Rect(K-1,L-1,3,3,GDB1
End

End
End
End
End
Return

I realized I didn't need a separate set of for loops for filling the neighbors on the change list, and that got it to run about 1.5x faster.

The method I'm using for filling the neighbors on the changelist still turns on a bunch of duplicate pixels if two pixels that are next to each other changed between generations (which happens a lot). I'm thinking there's probably not a much better way to do this, since all I can think of is using Pxl-tests to avoid filling duplicate cells, which probably wouldn't be any faster. If anyone has any ideas for this, they would be welcome.
  
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