// Author: Guillermo Rodriguez Garcia, <guille@iies.es>
// Modified by:
// Created: Jan/2000
-// RCS-ID: $Id$
// Copyright: (c) 2000, Guillermo Rodriguez Garcia
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _LIFE_GAME_H_
#define _LIFE_GAME_H_
-#ifdef __GNUG__
- #pragma interface "game.h"
-#endif
-
-// for compilers that support precompilation, includes "wx/wx.h"
-#include "wx/wxprec.h"
+// --------------------------------------------------------------------------
+// LifePattern
+// --------------------------------------------------------------------------
-#ifdef __BORLANDC__
- #pragma hdrstop
-#endif
+// A class which holds a pattern
+class LifePattern
+{
+public:
+ // This ctor is used by the LifeReader class
+ LifePattern(wxString name,
+ wxString description,
+ wxString rules,
+ wxArrayString shape)
+ {
+ m_name = name;
+ m_description = description;
+ m_rules = rules;
+ m_shape = shape;
+ };
-// for all others, include the necessary headers
-#ifndef WX_PRECOMP
- #include "wx/wx.h"
+ // A more convenient ctor for the built-in samples
+ LifePattern(wxString name,
+ wxString description,
+ int width,
+ int height,
+ const char *shape)
+ {
+ m_name = name;
+ m_description = description;
+ m_rules = wxEmptyString;
+ // TODO: add the positions later, since the formatting command
+ // causes a crash due to conversion objects not being available
+ // during initialisation.
+#ifndef __WXMAC__
+ m_shape.Add( wxString::Format(wxT("%i %i"), -width/2, -height/2) );
#endif
+ for(int j = 0; j < height; j++)
+ {
+ wxString tmp;
-// --------------------------------------------------------------------------
-// constants
-// --------------------------------------------------------------------------
+ for(int i = 0; i < width; i++)
+ {
+ tmp += wxChar(shape[j * width + i]);
+ }
-// minimum and maximum table size, in each dimension
-#define LIFE_MIN 20
-#define LIFE_MAX 200
+ m_shape.Add( tmp );
+ }
+ };
-// --------------------------------------------------------------------------
-// Cell and CellArray;
-// --------------------------------------------------------------------------
+ wxString m_name;
+ wxString m_description;
+ wxString m_rules;
+ wxArrayString m_shape;
+};
-typedef long Cell;
-typedef wxArrayLong CellArray;
// --------------------------------------------------------------------------
-// LifeShape
+// Life
// --------------------------------------------------------------------------
-class LifeShape
+// A struct used to pass cell coordinates around
+struct LifeCell
{
-public:
- LifeShape::LifeShape(wxString name,
- wxString desc,
- int width, int height, char *data,
- int fieldWidth = 20, int fieldHeight = 20,
- bool wrap = TRUE)
- {
- m_name = name;
- m_desc = desc;
- m_width = width;
- m_height = height;
- m_data = data;
- m_fieldWidth = fieldWidth;
- m_fieldHeight = fieldHeight;
- m_wrap = wrap;
- }
-
- wxString m_name;
- wxString m_desc;
- int m_width;
- int m_height;
- char *m_data;
- int m_fieldWidth;
- int m_fieldHeight;
- bool m_wrap;
+ wxInt32 i;
+ wxInt32 j;
};
-// --------------------------------------------------------------------------
-// Life
-// --------------------------------------------------------------------------
+// A private class that contains data about a block of cells
+class LifeCellBox;
+// A class that models a Life game instance
class Life
{
public:
// ctor and dtor
- Life(int width, int height);
+ Life();
~Life();
- void Create(int width, int height);
- void Destroy();
-
- // game field
- inline int GetWidth() const { return m_width; };
- inline int GetHeight() const { return m_height; };
- inline void SetBorderWrap(bool on) { m_wrap = on; };
-
- // cells
- bool IsAlive(int i, int j) const;
- bool IsAlive(Cell c) const;
- int GetX(Cell c) const;
- int GetY(Cell c) const;
- const CellArray* GetCells() const { return &m_cells; };
- const CellArray* GetChangedCells() const { return &m_changed; };
-
- // game logic
+
+ // accessors
+ inline wxUint32 GetNumCells() const { return m_numcells; };
+ inline wxString GetRules() const { return m_rules; };
+ inline wxString GetDescription() const { return m_description; };
+ bool IsAlive(wxInt32 x, wxInt32 y);
+ void SetCell(wxInt32 x, wxInt32 y, bool alive = true);
+ void SetPattern(const LifePattern &pattern);
+
+ // game control
void Clear();
- Cell SetCell(int i, int j, bool alive = TRUE);
- void SetShape(LifeShape &shape);
bool NextTic();
-private:
- int GetNeighbors(int i, int j) const;
- inline Cell MakeCell(int i, int j, bool alive) const;
-
- enum CellFlags
- {
- CELL_DEAD = 0x0000, // is dead
- CELL_ALIVE = 0x0001, // is alive
- CELL_MARK = 0x0002, // will change / has changed
- };
+ // navigation
+ LifeCell FindNorth();
+ LifeCell FindSouth();
+ LifeCell FindWest();
+ LifeCell FindEast();
+ LifeCell FindCenter();
+
+ // The following functions find cells within a given viewport; either
+ // all alive cells, or only those cells which have changed since last
+ // generation. You first call BeginFind() to specify the viewport,
+ // then keep calling FindMore() until it returns true.
+ //
+ // BeginFind:
+ // Specify the viewport and whether to look for alive cells or for
+ // cells which have changed since the last generation and thus need
+ // to be repainted. In this latter case, there is no distinction
+ // between newborn or just-dead cells.
+ //
+ // FindMore:
+ // Fills an array with cells that match the specification given with
+ // BeginFind(). The array itself belongs to the Life object and must
+ // not be modified or freed by the caller. If this function returns
+ // false, then the operation is not complete: just process all cells
+ // and call FillMore() again.
+ //
+ void BeginFind(wxInt32 x0, wxInt32 y0,
+ wxInt32 x1, wxInt32 y1,
+ bool changed);
+ bool FindMore(LifeCell *cells[], size_t *ncells);
- int m_width;
- int m_height;
- CellArray m_cells;
- CellArray m_changed;
- bool m_wrap;
+private:
+ // cellbox-related
+ LifeCellBox *CreateBox(wxInt32 x, wxInt32 y, wxUint32 hv);
+ LifeCellBox *LinkBox(wxInt32 x, wxInt32 y, bool create = true);
+ void KillBox(LifeCellBox *c);
+
+ // helper for BeginFind & FindMore
+ void DoLine(wxInt32 x, wxInt32 y, wxUint32 alive, wxUint32 old = 0);
+
+
+ // pattern description
+ wxString m_name; // name (currently unused)
+ wxString m_rules; // rules (currently unused)
+ wxString m_description; // description
+
+ // pattern data
+ LifeCellBox *m_head; // list of alive boxes
+ LifeCellBox *m_available; // list of reusable dead boxes
+ LifeCellBox **m_boxes; // hash table of alive boxes
+ wxUint32 m_numcells; // population (number of alive cells)
+
+ // state vars for BeginFind & FindMore
+ LifeCell *m_cells; // array of cells
+ size_t m_ncells; // number of valid entries in m_cells
+ wxInt32 m_x, m_y, // counters and search mode
+ m_x0, m_y0,
+ m_x1, m_y1;
+ bool m_changed;
+ bool m_findmore;
};
#endif // _LIFE_GAME_H_