Conway's game of life - derived from another project, turned into a c++ class, and scaled to support up to a 480x272 display, or a lower resolution color display.

Dependents:   GameOfLife

Revision:
1:9e88d16ab21e
Parent:
0:d43dc92ae767
Child:
2:c11005ab38db
--- a/LifeRules.h	Wed Apr 16 22:25:19 2014 +0000
+++ b/LifeRules.h	Wed Apr 23 11:40:10 2014 +0000
@@ -1,10 +1,22 @@
-
+/// Conway's game of life
+///
+/// http://en.wikipedia.org/wiki/Conway's_Game_of_Life
+///
+/// A simple cellular automation where pixels are born, live, and die
+/// following a simple set of rules. The oddest of the rules is that
+/// it takes 3 to create birth of a new life...
+///
+/// Early on (back in the 70's), computers were not accessible to
+/// most, and yet somehow this simulation flourished. I was one of
+/// many that used pencil and graph paper, chalk on a board and
+/// even pennies on paper to simulate each cell. It was so much 
+/// more animated when I had access to an 8008 micro and a "TV 
+/// typewriter" interface.
+///
 #include "mbed.h"
 
 // Defined and Derived values to check if it exceeds available memory
-//#define BITS_PER_LIFE 2     /* 0, 1, 2, 3 provides a more colorful view of life */
 #define FRAMES_PER_BIT 2    /* current and next life cycle */
-#define BYTE_RSVD_RAM 0x8000
 
 //#if (LIFE_W * LIFE_H * BITS_PER_LIFE * FRAMES_PER_BIT / 8) > (BYTE_RSVD_RAM)
 //#error Bummer, can't make the lifemap that big
@@ -27,33 +39,121 @@
 
     /// constructor for the life 
     ///
-    /// @param w is the width of the life map
-    /// @param h is the height of the life map
+    /// Constructor for the life object. The most important thing
+    /// when constructing life, is to have room for the occupants,
+    /// so take care that memory is actually available for the 
+    /// life map on your system.
+    ///
+    /// The required memory in bits is:
+    ///
+    ///    w * h * 2 * (animate == color) ? 2 : 1
+    ///
+    /// The '2' is because it keeps a current generation map and
+    /// a next generation map.
+    ///
+    /// As an example:
+    ///   480 * 272 * 2 * 1 => 261120 bits => 32640 bytes
+    /// 
+    /// Fragments from a sample application you might find in main.cpp
+    /// are shown here, this one for the RA8875 display graphics
+    /// library. (see http://mbed.org/components/RA8875-Based-Display/)
     ///
-    Life(int w, int h, Animation animate = color);
+    /// @code
+    /// #define SCREEN_W 480
+    /// #define SCREEN_H 272
+    /// Life life(LIFE_W, LIFE_H, Life::monochrome);
+    /// RA8875 lcd(p5, p6, p7, p12, NC, "tft");
+    /// 
+    /// // Where on screen do we locate it?
+    /// #define LIFE_OFFSET_X (SCREEN_W - LIFE_W)
+    /// #define LIFE_OFFSET_Y (SCREEN_H - LIFE_H)
+    /// 
+    /// int main()
+    /// {
+    ///     life.setbit(1,1, Life::living);
+    ///     life.setbit(1,2, Life::living);
+    ///     life.setbit(1,3, Life::living);
+    ///     while(1) {
+    ///         static uint16_t toggle = 0;
+    ///         if ((++toggle & 1) == 0) {
+    ///             life.GenerationStep();
+    ///         } else {
+    ///             life.UpdateLifeCycle();
+    ///         }
+    ///         ScreenUpdate();
+    ///     }
+    /// }
+    /// 
+    /// void ScreenUpdate()
+    /// {
+    ///     lcd.window(LIFE_OFFSET_X, LIFE_OFFSET_Y, LIFE_W, LIFE_H);
+    ///     lcd._StartGraphicsStream();
+    ///     for (int j = 0; j < LIFE_H; j++) {
+    ///         for (int i = 0; i < LIFE_W; i++) {
+    ///             Life::ValueOfLife lifeState = life.getbit(i,j);
+    ///             switch (lifeState) {
+    ///                 case Life::dead:
+    ///                     lcd._putp(Black);
+    ///                     break;
+    ///                 case Life::dying:
+    ///                     lcd._putp(RGB(64,0,0));
+    ///                     break;
+    ///                 case Life::living:
+    ///                     lcd._putp(Charcoal);
+    ///                     break;
+    ///                 case Life::birthing:
+    ///                     lcd._putp(Blue);
+    ///                     break;
+    ///                 default:
+    ///                     lcd._putp(Orange);
+    ///                     ERR(" lifeState = %d\r\n", lifeState);
+    ///                     break;
+    ///             }
+    ///         }
+    ///     }
+    ///     lcd._EndGraphicsStream();
+    ///     lcd.WindowMax();
+    /// }
+    /// @endcode
+    /// 
+    /// @param[in] w is the width of the life map in pixels, commonly
+    ///     chosen to match the display device capability.
+    /// @param[in] h is the height of the life map in pixels, commonly
+    ///     chosen to match the display device capability.
+    /// @param[in] animate is an optional parameter that can be either 
+    ///     'monochrome' or 'color' (the default), which determines 
+    ///     if each life cycle has one step (e.g. from life directly 
+    ///     to death) or two steps (e.g. life to dying to death).
+    /// @param[in] pMap is an optional pointer to a block of memory to 
+    ///     host the life map. If not specified, it will assume
+    ///     the memory space of an LPC1768 where the 32K Ethernet
+    ///     buffers are not being used (and take that space for the
+    ///     life map).
+    ///
+    Life(int w, int h, Animation animate = color, uint8_t * pMap = (uint8_t *)(0x2007C000));
 
     /// sets a life value in the frame at location x,y.
     ///
-    /// @param x is the x location in the life-map
-    /// @param y is the y location in the life-map
-    /// @param otherframe selects the next life-cycle of interest
-    /// @param b is the value of life to assign to that location
+    /// @param[in] x is the x location in the life-map
+    /// @param[in] y is the y location in the life-map
+    /// @param[in] otherframe selects the next life-cycle of interest
+    /// @param[in] b is the value of life to assign to that location
     /// 
     void setbit(int x, int y, ValueOfLife b, int otherframe = 0);
 
     /// gets the life value from the specified location.
     ///
-    /// @param x is the x location in the life-map
-    /// @param y is the y location in the life-map
-    /// @param otherframe selects the next life-cycle of interest
+    /// @param[in] x is the x location in the life-map
+    /// @param[in] y is the y location in the life-map
+    /// @param[in] otherframe selects the next life-cycle of interest
     /// @returns the value of life at that location.
     ///
     ValueOfLife getbit(int x, int y, int otherframe = 0);
 
     /// Count and return the number of living neighbors.
     /// 
-    /// @param x is the x location in the life-map
-    /// @param y is the y location in the life-map
+    /// @param[in] x is the x location in the life-map
+    /// @param[in] y is the y location in the life-map
     /// @returns the number of neighbors
     /// 
     int CountNeighbors(int x, int y);
@@ -81,21 +181,19 @@
     /// state of a cell, this determines whether the cell
     /// is born, lives, or dies.
     ///
-    /// @param x is the x offset into the life map.
-    /// @param y is the y offset into the life map.
-    /// @param neighbors is the count of neighbors.
+    /// @param[in] x is the x offset into the life map.
+    /// @param[in] y is the y offset into the life map.
+    /// @param[in] neighbors is the count of neighbors.
     ///
     void CycleOfLife(int x, int y, int neighbors);
 
 private:
-    int LIFE_W;
+    int LIFE_W;     // dimensions of the life map
     int LIFE_H;
-    int maxX;   // set max element
+    int maxX;       // set max element for ease of iterations
     int maxY;
-    int frame;  // the current life cycle
-    int animation;
-    
-    // CAUTION: This gives a pointer to a 32K byte range which is all being used!
+    int frame;      // the current life cycle
+    int animation;  // mode - color or b&w
     uint8_t * pLifeMap;
 };
     
\ No newline at end of file