1/////////////////////////////////////////////////////////////////////////////
2// Name:        game.h
3// Purpose:     Life! game logic
4// Author:      Guillermo Rodriguez Garcia, <guille@iies.es>
5// Modified by:
6// Created:     Jan/2000
7// RCS-ID:      $Id: game.h 38363 2006-03-25 12:04:37Z JS $
8// Copyright:   (c) 2000, Guillermo Rodriguez Garcia
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifndef _LIFE_GAME_H_
13#define _LIFE_GAME_H_
14
15// for compilers that support precompilation, includes "wx/wx.h"
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19    #pragma hdrstop
20#endif
21
22// for all others, include the necessary headers
23#ifndef WX_PRECOMP
24    #include "wx/wx.h"
25#endif
26
27// --------------------------------------------------------------------------
28// LifePattern
29// --------------------------------------------------------------------------
30
31// A class which holds a pattern
32class LifePattern
33{
34public:
35    // This ctor is used by the LifeReader class
36    LifePattern(wxString      name,
37                wxString      description,
38                wxString      rules,
39                wxArrayString shape)
40    {
41        m_name        = name;
42        m_description = description;
43        m_rules       = rules;
44        m_shape       = shape;
45    };
46
47    // A more convenient ctor for the built-in samples
48    LifePattern(wxString      name,
49                wxString      description,
50                int           width,
51                int           height,
52                const char   *shape)
53    {
54        m_name        = name;
55        m_description = description;
56        m_rules       = wxEmptyString;
57        // TODO: add the positions later, since the formatting command
58        // causes a crash due to conversion objects not being available
59        // during initialisation.
60#ifndef __WXMAC__
61        m_shape.Add( wxString::Format(_T("%i %i"), -width/2, -height/2) );
62#endif
63        for(int j = 0; j < height; j++)
64        {
65            wxString tmp;
66
67            for(int i = 0; i < width; i++)
68            {
69                tmp += wxChar(shape[j * width + i]);
70            }
71
72            m_shape.Add( tmp );
73        }
74    };
75
76    wxString      m_name;
77    wxString      m_description;
78    wxString      m_rules;
79    wxArrayString m_shape;
80};
81
82
83// --------------------------------------------------------------------------
84// Life
85// --------------------------------------------------------------------------
86
87// A struct used to pass cell coordinates around
88struct LifeCell
89{
90    wxInt32 i;
91    wxInt32 j;
92};
93
94// A private class that contains data about a block of cells
95class LifeCellBox;
96
97// A class that models a Life game instance
98class Life
99{
100public:
101    // ctor and dtor
102    Life();
103    ~Life();
104
105    // accessors
106    inline wxUint32 GetNumCells() const    { return m_numcells; };
107    inline wxString GetRules() const       { return m_rules; };
108    inline wxString GetDescription() const { return m_description; };
109    bool IsAlive(wxInt32 x, wxInt32 y);
110    void SetCell(wxInt32 x, wxInt32 y, bool alive = true);
111    void SetPattern(const LifePattern &pattern);
112
113    // game control
114    void Clear();
115    bool NextTic();
116
117    // navigation
118    LifeCell FindNorth();
119    LifeCell FindSouth();
120    LifeCell FindWest();
121    LifeCell FindEast();
122    LifeCell FindCenter();
123
124    // The following functions find cells within a given viewport; either
125    // all alive cells, or only those cells which have changed since last
126    // generation. You first call BeginFind() to specify the viewport,
127    // then keep calling FindMore() until it returns true.
128    //
129    // BeginFind:
130    //  Specify the viewport and whether to look for alive cells or for
131    //  cells which have changed since the last generation and thus need
132    //  to be repainted. In this latter case, there is no distinction
133    //  between newborn or just-dead cells.
134    //
135    // FindMore:
136    //  Fills an array with cells that match the specification given with
137    //  BeginFind(). The array itself belongs to the Life object and must
138    //  not be modified or freed by the caller. If this function returns
139    //  false, then the operation is not complete: just process all cells
140    //  and call FillMore() again.
141    //
142    void BeginFind(wxInt32 x0, wxInt32 y0,
143                   wxInt32 x1, wxInt32 y1,
144                   bool changed);
145    bool FindMore(LifeCell *cells[], size_t *ncells);
146
147private:
148    // cellbox-related
149    LifeCellBox *CreateBox(wxInt32 x, wxInt32 y, wxUint32 hv);
150    LifeCellBox *LinkBox(wxInt32 x, wxInt32 y, bool create = true);
151    void KillBox(LifeCellBox *c);
152
153    // helper for BeginFind & FindMore
154    void DoLine(wxInt32 x, wxInt32 y, wxUint32 alive, wxUint32 old = 0);
155
156
157    // pattern description
158    wxString   m_name;          // name (currently unused)
159    wxString   m_rules;         // rules (currently unused)
160    wxString   m_description;   // description
161
162    // pattern data
163    LifeCellBox   *m_head;          // list of alive boxes
164    LifeCellBox   *m_available;     // list of reusable dead boxes
165    LifeCellBox  **m_boxes;         // hash table of alive boxes
166    wxUint32   m_numcells;      // population (number of alive cells)
167
168    // state vars for BeginFind & FindMore
169    LifeCell  *m_cells;         // array of cells
170    size_t     m_ncells;        // number of valid entries in m_cells
171    wxInt32    m_x, m_y,        // counters and search mode
172               m_x0, m_y0,
173               m_x1, m_y1;
174    bool       m_changed;
175    bool       m_findmore;
176};
177
178#endif  // _LIFE_GAME_H_
179