summaryrefslogtreecommitdiff
path: root/server/game.h
blob: c8c5d6aaa9ef90f229e91b99de04d0d044ed1953 (plain)
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
#ifndef GAME_H
#define GAME_H

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <vector>

#include "wall.h"
#include "client.h"
#include "../common/action.h"
#include "../common/set.h"
#include "../common/state.h"
#include "../common/cyclicint.h"

class Game : public boost::enable_shared_from_this<Game> {
	public:
		typedef boost::shared_ptr<Game> p;
		
		static p create(ClientBase::p player_1, ClientBase::p player_2, ClientBase::p player_3, ClientBase::p player_4);
		
		~Game();
		
	private:
		typedef CyclicInt<4> PlayerNum;
		
		class Player {
			public:
				ClientBase::p client;
				
				Tiles hand;
				Sets open;
				Tiles pond;
				bool riichi;
				int score;
				int wind;
				
				//! Indexes of tiles that will give tenpai (used after riichi declaration).
				List<int> tenpai_indexes;
				
				//! Prepare for a new round.
				void round_start(int w);
				
				//! Get a state snapshot.
				PlayerState get_state();
				
				//! Get a state snapshot, with concealed tiles filtered.
				PlayerState get_state_filtered();
				
				//! Get possible actions after a draw.
				Actions get_actions_draw();
				
				//! Get possible actions on discarded tile.
				Actions get_actions_discard(Tile tile, PlayerNum discarder);
				
				typedef std::vector<int> Targets;
				
				//! Check if player can declare riichi.
				bool can_riichi();
				
				//! Check if tile can be called for a chi.
				Targets can_chi(Tile tile);
				
				//! Check if tile can be called for a pon.
				int can_pon(Tile tile);
				
				//! Check if it's possible to make a concealed kan.
				Targets can_kan();
				
				//! Check if it's possible to extend a pon to a kan.
				Targets can_kan_extend();
				
				//! Check if tile can be called to kan target.
				bool can_kan(Tile tile, int target);
				
				//! Check if hand is complete.
				bool can_tsumo();
				
				//! Check if tile can be called to complete hand.
				bool can_ron(Tile tile);
				
				//! Draw tile.
				void draw(Tile tile);
				
				//! Discard tile.
				void discard(int target);
				
				//! Look at last discard in pond.
				Tile last_discard();
				
				//! Claim last discard from pond.
				Tile claim();
				
				//! Declare riichi.
				void declare_riichi();
				
				//! Make chi from tile.
				void make_chi(Tile tile, int target);
				
				//! Make pon from tile.
				void make_pon(Tile tile, int target, PlayerNum discarder);
				
				//! Make open kan from tile.
				void make_kan(Tile tile, int target, PlayerNum discarder);
				
				//! Make concealed kan.
				void make_kan(int target);
				
				//! Make extended kan.
				void make_kan_extend(int target);
		};
		
		Player players[4];
		
		Wall wall;
		
		Tiles dora;
		
		bool kan_dora_pending;
		
		PlayerNum current_player;
		
		PlayerNum round_wind;
		PlayerNum round_num;
		
		int awaiting_players;
		
		Action preceding_action;
		int preceding_action_owner;
		
		Game(ClientBase::p player_1, ClientBase::p player_2, ClientBase::p player_3, ClientBase::p player_4);
		
		//! Handle Ready message from player.
		void handle_ready();
		
		//! Start the game.
		void start();
		
		//! Start a new round.
		void round_start();
		
		//! Send update after a tile is drawn.
		void round_update_draw();
		
		//! Send update after a tile is discarded.
		void round_update_discard();
		
		//! Handle action after draw.
		void handle_action_draw(Action action);
		
		//! Handle actions after discard.
		void handle_action_discard(Action action, int player);
		
		//! End the game.
		void round_end();
};

#endif