1 // This file is part of Golly.
2 // See docs/License.html for the copyright notice.
3 
4 /**
5  *   This class implements the rules supported by QuickLife and HashLife.
6  *   A rule lookup table is used for computing a new 2x2 grid from
7  *   a provided 4x4 grid (two tables are used to emulate B0-not-Smax rules).
8  *   The input is a 16-bit integer, with the most significant bit the
9  *   upper left corner, bits going horizontally and then down.  The output
10  *   is a 6-bit integer, with the top two bits indicating the top row of
11  *   the 2x2 output grid and the least significant two bits indicating the
12  *   bottom row.  The middle two bits are always zero.
13  */
14 #ifndef LIFERULES_H
15 #define LIFERULES_H
16 #include "lifealgo.h"
17 const int MAXRULESIZE = 500 ;  // maximum number of characters in a rule
18 const int ALL3X3 = 512 ;       // all possible 3x3 cell combinations
19 const int ALL4X4 = 65536 ;     // all possible 4x4 cell combinations
20 const int MAP512LENGTH = 86 ;  // number of base64 characters to encode 512bit map for Moore neighborhood
21 const int MAP128LENGTH = 22 ;  // number of base64 characters to encode 128bit map for Hex neighborhood
22 const int MAP32LENGTH  = 6 ;   // number of base64 characters to encode 32bit map for von Neumann neighborhood
23 
24 class liferules {
25 public:
26    liferules() ;
27    ~liferules() ;
28    // string returned by setrule is any error
29    const char *setrule(const char *s, lifealgo *algo) ;
30    const char *getrule() ;
31 
32    // AKT: we need 2 tables to support B0-not-Smax rule emulation
33    // where max is 8, 6 or 4 depending on the neighborhood
34    char rule0[ALL4X4] ;      // rule table for even gens if rule has B0 but not Smax,
35                              // or for all gens if rule has no B0, or it has B0 *and* Smax
36    char rule1[ALL4X4] ;      // rule table for odd gens if rule has B0 but not Smax
37    bool alternate_rules ;    // set by setrule; true if rule has B0 but not Smax
38 
39    // AKT: support for various neighborhoods
40    // rowett: support for non-totalistic isotropic rules
41    enum neighborhood_masks {
42       MOORE = 0x1ff,         // all 8 neighbors
43       HEXAGONAL = 0x0fe,     // ignore NE and SW neighbors
44       VON_NEUMANN = 0x0ba    // 4 orthogonal neighbors
45    } ;
46 
47    bool isRegularLife() ;    // is this B3/S23?
isHexagonal()48    bool isHexagonal() const { return neighbormask == HEXAGONAL ; }
isVonNeumann()49    bool isVonNeumann() const { return neighbormask == VON_NEUMANN ; }
isWolfram()50    bool isWolfram() const { return wolfram >= 0 ; }
51 
52 private:
53    char canonrule[MAXRULESIZE] ;      // canonical version of valid rule passed into setrule
54    neighborhood_masks neighbormask ;  // neighborhood masks in 3x3 table
55    bool totalistic ;                  // is rule totalistic?
56    bool using_map ;                   // is rule a map?
57    int neighbors ;                    // number of neighbors
58    int rulebits ;                     // bitmask of neighbor counts used (9 birth, 9 survival)
59    int letter_bits[18] ;              // bitmask for non-totalistic letters used
60    int negative_bit ;                 // bit in letters bits mask indicating negative
61    int wolfram ;                      // >= 0 if Wn rule (n is even and <= 254)
62    int survival_offset ;              // bit offset in rulebits for survival
63    int max_letters[18] ;              // maximum number of letters per neighbor count
64    const int *order_letters[18] ;     // canonical letter order per neighbor count
65    const char *valid_rule_letters ;   // all valid letters
66    const char *rule_letters[4] ;      // valid rule letters per neighbor count
67    const int *rule_neighborhoods[4] ; // isotropic neighborhoods per neighbor count
68    char rule3x3[ALL3X3] ;             // all 3x3 cell mappings 012345678->4'
69    const char *base64_characters ;    // base 64 encoding characters
70 
71    void initRule() ;
72    void setTotalistic(int value, bool survival) ;
73    int flipBits(int x) ;
74    int rotateBits90Clockwise(int x) ;
75    void setSymmetrical512(int x, int b) ;
76    void setSymmetrical(int value, bool survival, int lindex, int normal) ;
77    void setTotalisticRuleFromString(const char *rule, bool survival) ;
78    void setRuleFromString(const char *rule, bool survival) ;
79    void createWolframMap() ;
80    void createRuleMapFromMAP(const char *base64) ;
81    void createRuleMap(const char *birth, const char *survival) ;
82    void convertTo4x4Map(char *which) ;
83    void saveRule() ;
84    void createCanonicalName(lifealgo *algo, const char *base64) ;
85    void removeChar(char *string, char skip) ;
86    bool lettersValid(const char *part) ;
87    int addLetters(int count, int p) ;
88 } ;
89 #endif
90