source: trunk/gamelogic.hxx @ 14

Last change on this file since 14 was 5, checked in by jtv, 14 years ago

Implemented saving/restoring of game state

File size: 5.7 KB
Line 
1/*
2This file is part of libmines.
3
4Copyright (C) 2005, Jeroen T. Vermeulen <jtv@xs4all.nl>
5
6libmines is free software; you can redistribute it and/or modify it under the
7terms of the GNU General Public License as published by the Free Software
8Foundation; either version 2 of the License, or (at your option) any later
9version.
10
11libmines is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13PARTICULAR PURPOSE.  See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License along with
16libmines; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
17Suite 330, Boston, MA  02111-1307  USA
18*/
19
20// This file defines the native C++ API to libmines
21
22#include <set>
23
24/// Coordinates of a patch of sea
25struct Coords
26{
27  int row;
28  int col;
29  Coords(int Row, int Col) : row(Row), col(Col) {}
30  bool operator<(const Coords &rhs) const throw ()
31        { return (rhs.row < row) || (rhs.row==row && rhs.col<col); }
32};
33
34
35/// Exception thrown when a mine is hit
36struct Boom
37{
38  Coords position;
39  int moves;
40  bool mined;
41  Boom(Coords pos, int mov, bool mine) : position(pos), moves(mov), mined(mine)
42        {}
43};
44
45
46class Patch;
47
48/// The "minefield."  This is where it all happens.
49/** The Lake is a rectangle of square Patches, each of which may or may not have
50 * a mine in it.  In the internal representation, the Lake is surrounded by a
51 * border of clear Patches, which are not shown.  This means there are fewer
52 * special cases in the algorithm for border Patches.  They do complicate the
53 * array indexing and such, but all that is nicely hidden here.
54 */
55class Lake
56{
57public:
58  /// Start new game
59  Lake(int rows, int cols, int mines);
60  /// Start game from saved game state
61  explicit Lake(const char[]);
62
63  ~Lake() throw ();
64
65  /// Maximum intelligence level available
66  static int max_intelligence() throw () { return 2; }
67
68  /// Change intelligence level
69  void set_intelligence(int i) throw () { m_intelligence = i; }
70
71  /// Mark given patch as being either clear or mined
72  /** The specified amount of "intelligence" is recursively applied in revealing
73   * surrounding patches whose state becomes obvious.  Boom is thrown if the
74   * given patch is actually mined.
75   * @param changes will receive a list of all patches revealed by this move
76   * @param as_mine indicates whether user thinks this patch is mined
77   */
78  void probe(int row, int col, std::set<Coords> &changes, bool as_mine=false);
79
80  /// Number of unmined patches still to be revealed
81  int to_go() const throw () { return m_patches_to_go; }
82
83  /// Number of moves made
84  int moves() const throw () { return m_moves; }
85
86  /// Status representation of patch at given coordinates
87  /** Returns '^' for unexplored water; '*' for a known mine; or the single
88   * textual digit representing the number of nearby mines.
89   *
90   * Coordinates are zero-based.  Patches "just outside" the playing field (i.e.
91   * having coordinates of -1 or the exact number of rows/columns respectively)
92   * may be safely queried.
93   */
94  char status_at(int row, int col) const;
95
96  const int rows() const throw () { return m_rows; }
97  const int cols() const throw () { return m_cols; }
98
99  /// Write game state (in ASCII) to memory buffer
100  /** The available buffer space must be at least rows*cols+100 bytes large.
101   */
102  int save(char buf[]) const;
103
104private:
105  enum { border = 3 };
106  Patch &at(int row, int col);
107  const Patch &at(int row, int col) const;
108
109  void init_field();
110
111  bool place_mine_at(int row, int col);
112
113  /// Apply functor f to a square of Patches centered at (row,col)
114  /** The INCLUDECENTER template argument determines whether the central patch
115   * should be included in this square, or whether it should be skipped.
116   */
117  template<int RADIUS, bool INCLUDECENTER, typename FUNCT>
118  void for_zone(int row, int col, FUNCT f)
119  {
120    const int top = std::max(-border, row-RADIUS),
121              bottom = std::min(row+RADIUS+1, m_rows+border),
122              left = std::max(-border, col-RADIUS),
123              right = std::min(col+RADIUS+1, m_cols+border);
124
125    for (int r = top; r < bottom; ++r) for (int c = left; c < right; ++c)
126      if (INCLUDECENTER || r!=row || c!=col)
127        f(Coords(r,c),at(r,c));
128  }
129
130  template<typename FUNCT> void for_neighbours(int row, int col, FUNCT f)
131        { return for_zone<1,false>(row,col,f); }
132
133  void reveal_patch(int row, int col);
134
135  /// Initialize a row of patches in the lake's border
136  void border_row(int);
137  /// Initialize a row of patches in the lake's border
138  void border_col(int);
139
140  /// Recursively reveal any patches whose status becomes or has become obvious
141  /** This is where the intelligence level is applied in order to expose patches
142   * that become obvious.
143   *
144   * Intelligence may currently be 0 ("don't reveal anything except at the
145   * user's request"); 1 ("only reveal patches with zero neighbouring mines and
146   * their immediate neighbours"); or 2 ("reveal any mines that have had all
147   * their surrounding mines revealed, or have as many surrounding unexplored
148   * mines as they have surrounding unexplored fields").  Most minesweeper
149   * implementations implement level 1.
150   *
151   * Higher intelligence levels are accepted, but do not instill any greater
152   * intelligence than is implemented.  More levels will be added in the future.
153   */
154  void propagate(std::set<Coords> &work, std::set<Coords> &changes);
155
156  int index_for(int row, int col) const throw ();
157  int arraysize() const throw ();
158  void check_index(int) const;
159  void check_pos(int row, int col) const;
160
161  Patch *m_patches;
162  int m_rows, m_cols;
163  int m_intelligence;
164  int m_patches_to_go;
165  int m_moves;
166
167  Lake();
168  Lake(const Lake &);
169  const Lake &operator=(const Lake &);
170};
171
Note: See TracBrowser for help on using the repository browser.