File: game.h

package info (click to toggle)
atom4 4.1-6
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 656 kB
  • ctags: 947
  • sloc: cpp: 4,461; makefile: 54; sh: 21; perl: 6
file content (168 lines) | stat: -rw-r--r-- 5,293 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
 * Atom-4 game engine
 * Header file
 * ---------------------------------------------------------------------------
 * $Id: game.h,v 1.20 2003/04/15 00:24:21 hsteoh Exp hsteoh $
 *
 * DESIGN
 *
 * This game engine is supposed to be UI-driven; so it is basically designed
 * for an event-driven interface. The UI, whether the testing ncurses-based
 * UI or the anticipated X11 UI, will be sending events to class atom4 and
 * checking its state to know what to do next, etc.. Basically, this class
 * implements the game rules.
 */

#ifndef GAME_H
#define GAME_H

#include <list.h>			// MUST be prog/lib version!
#include "board4.h"
#include "color4.h"
#include "triboard.h"


#define STALEMATE		3	// returned by atom4::winner()

#define NUM_COLORS		8
#define NUM_PLAYERS		2

#define WIN_ROW			4	// number of pieces in a row to win

// Internal stuff
#define COLORSEQ_LEN		6


// Callback class for handling allowing async notification of game state
// changes
class atom4;				// forward decl
class atom4notifier {
public:
  // Notify of all game state changes
  virtual void notify_move(atom4 *src, int plr, elist<boardchange> &chg)=0;
  virtual void notify_clear(atom4 *src)=0;
};

// Abstract base class
class atom4 {
  elist<atom4notifier*> notifylist;
protected:
  // Send notification to all registered notifiers. Derived classes must
  // call this every time a game state change is detected.
  virtual void notify_move(int player, elist<boardchange> &changes);
  virtual void notify_clear();
public:
  enum mode_t {
    DUAL,				// both players connected to interface
    PEER,				// one player connected to interface
    WATCH				//  not actively participating
  };

  virtual ~atom4();
  virtual void reset()=0;		// restart game

  virtual mode_t game_mode()=0;		// return current mode
  virtual int local_playernum()=0;	// assigned player number if in PEER
					// mode; current_player() if DUAL mode,
					// -1 if WATCH mode.
  virtual int is_local_turn()=0;
  void add_notifier(atom4notifier *callback);		// [R]
  void remove_notifier(atom4notifier *callback);	// [R]

  virtual int current_player()=0;
  virtual celltype current_tile()=0;
  
  // Returns false if move is illegal (not player's turn, bad position, game
  // already over, etc.), true otherwise.
  virtual int move(int player, int x, int y)=0;
  
  // Checks if move is legal (note: this does NOT guarantee a subsequent
  // call to move() will be successful, since this only checks the board
  // not the current state of the game)
  virtual int check_legal(int x, int y)=0;

  virtual int round_over()=0;
  virtual int winner()=0;

  // Multi-round support
  virtual int current_round()=0;
  virtual int newround()=0;
  virtual int score(int player)=0;

  // FIXME: what we REALLY want is to have a way to register an update
  // callback with class triboard, that will get called every time a cell
  // changes. (This is the REAL answer to the whole mess in the X11 refresh()
  // code right now...)
  virtual board4 *get_board()=0;
  virtual unsigned int board_width()=0;
  virtual unsigned int board_height()=0;
};

class atom4local : public atom4 {
  board4 *board;			// [O] game board

  int win_player;			// player who won the game; if not -1,
					// game is over.
  int cur_player;			// player to make the next move
  int cur_color;			// which color is being played
  static celltype colorseq[COLORSEQ_LEN];

  // Multi-round stuff
  int cur_round;			// current round
  int start_player;			// player to move first
  int scores[NUM_PLAYERS];

  // Internal convenience stuff
  inline char plchar(int player) { return 'a' + player-1; }
  inline int next_player(int player) { return player%NUM_PLAYERS + 1; }
  inline int valid_player(int pl) { return pl>0 && pl<=NUM_PLAYERS; }

  inline int next_color(int color) { return (color+1)%COLORSEQ_LEN; }

  int splash(int bx, int by, color4 actor, elist<boardchange> &changes);
  void reset_scores();
  void reset_board();
public:
  atom4local(unsigned int width, unsigned int height);
  virtual ~atom4local();
  virtual void reset();			// restart game

  virtual mode_t game_mode();		// return current mode
  virtual int local_playernum();
  virtual int is_local_turn();

  // For UI to know who's supposed to move next. UI should not need to keep
  // track of this independently anyway.
  int current_player();

  // Current marble (which color) being played
  celltype current_tile();

  // Returns false if move is illegal (not player's turn, bad position, game
  // already over, etc.), true otherwise.
  int move(int player, int x, int y);

  // Checks if move is legal (note: this does NOT guarantee a subsequent
  // call to move() will be successful, since this only checks the board
  // not the current state of the game)
  int check_legal(int x, int y);

  int round_over();
  int winner();

  // Multi-round support
  int current_round();
  virtual int newround();
  int score(int player);

  // FIXME: what we REALLY want is to have a way to register an update
  // callback with class triboard, that will get called every time a cell
  // changes. (This is the REAL answer to the whole mess in the X11 refresh()
  // code right now...)
  board4 *get_board();
  unsigned int board_width();
  unsigned int board_height();
};


#endif // GAME_H