1 #ifndef GLOBALDATA_DEFINE
2 #define GLOBALDATA_DEFINE
3 /*
4  * atanks - obliterate each other with oversize weapons
5  * Copyright (C) 2003  Thomas Hudson
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  */
22 
23 #include "main.h"
24 
25 
26 #include <sys/types.h>
27 #include <atomic>
28 
29 
30 #ifndef HAS_DIRENT
31 #  if defined(ATANKS_IS_MSVC)
32 #    include "extern/dirent.h"
33 #  else
34 #    include <dirent.h>
35 #  endif // Linux
36 #  define HAS_DIRENT 1
37 #endif //HAS_DIRENT
38 
39 
40 #ifdef USE_MUTEX_INSTEAD_OF_SPINLOCK
41 #  include <mutex>
42 #  define CSpinLock std::mutex
43 #endif // USE_MUTEX_INSTEAD_OF_SPINLOCK
44 
45 
46 #include "text.h"
47 #include "globaltypes.h"
48 #include "environment.h"
49 
50 
51 extern int32_t BLACK;
52 
53 
54 /// Forwards that do not need to be known here
55 struct sDebrisItem;
56 struct sDebrisPool;
57 class PLAYER;
58 class TANK;
59 class VIRTUAL_OBJECT;
60 
61 
62 #ifndef USE_MUTEX_INSTEAD_OF_SPINLOCK
63 /** @brief minimal spinlock class
64   * It can do nothing but lock and unlock. No recursive locks.
65   * But then it is a lot faster and leaner than mutexes and critical
66   * sections ever can be. ;)
67 **/
68 class CSpinLock
69 {
70 public:
71 	explicit CSpinLock();
72     ~CSpinLock();
73 
74     CSpinLock(const CSpinLock&)            = delete;
75     CSpinLock &operator=(const CSpinLock&) = delete;
76 
77 	bool hasLock();
78 	void lock();
79 	void unlock();
80 private:
81 
82 	abool_t          is_destroyed;
83 	aflag_t          lock_flag;
84 	std::thread::id  owner_id;
85 };
86 #endif // USE_MUTEX_INSTEAD_OF_SPINLOCK
87 
88 
89 /** @class GLOBALDATA
90   * @brief Values used globally during a game round.
91   *
92   * This class holds all values and the corresponding functions for everything
93   * that can change during a game round.
94   *
95   * Everything that is fixed during a game round is consolidated in ENVIRONMENT.
96 **/
97 class GLOBALDATA
98 {
99 	typedef VIRTUAL_OBJECT vobj_t;
100 	typedef sDebrisItem    item_t;
101 
102 public:
103 
104 	/* -----------------------------------
105 	 * --- Constructors and destructor ---
106 	 * -----------------------------------
107 	 */
108 
109 	explicit GLOBALDATA ();
110 	~GLOBALDATA();
111 
112 
113 	/* ----------------------
114 	 * --- Public methods ---
115 	 * ----------------------
116 	 */
117 	void    addLandSlide      (int32_t left, int32_t right, bool do_lock);
118 	void    addObject         (vobj_t* object);
119 	bool    areTanksInBox     (int32_t x1, int32_t y1, int32_t x2, int32_t y2);
120 	bool    check_time_changed(); // check to see if one second has passed
121 	void    clear_objects     ();
122 	void    destroy           ();
123 	void    do_updates        ();
124 	void    first_init        ();
125 	void    free_debris_item  (item_t* item);
126 	int32_t get_avg_bgcolor   (int32_t x1, int32_t y1, int32_t x2, int32_t y2,
127 	                           double xv, double yv);
128 	int32_t get_command       ();
129 	TANK*   get_curr_tank     ();
130 	item_t* get_debris_item   (int32_t radius);
131 	TANK*   get_next_tank     (bool* wrapped_around);
132 	void    initialise        ();
133 	bool    isCloseBtnPressed ();
134 	bool    isDirtInBox       (int32_t x1, int32_t y1, int32_t x2, int32_t y2);
135 	void    load_from_file    (FILE* file);
136 	void    lockClass         (eClasses class_);
137 	void    lockLand          ();
138 	void    make_bgupdate     (int32_t x, int32_t y, int32_t w, int32_t h);
139 	void    make_fullUpdate   ();
140 	void    make_update       (int32_t x, int32_t y, int32_t w, int32_t h);
141 	void    newRound          ();
142 	void    pressCloseButton  ();
143 	void    removeObject      (vobj_t* object);
144 	void    removeTank        (TANK* tank);
145 	void    replace_canvas    ();
146 	bool    save_to_file      (FILE* file);
147 	void    set_curr_tank     (TANK* tank_);
148 	void    set_command       (int32_t cmd);
149 	void    slideLand         ();
150 	void    unlockClass       (eClasses class_);
151 	void    unlockLand        ();
152 	void    unlockLandSlide   (int32_t left, int32_t right);
153 
154 	template<typename Head_T>
getHeadOfClass(eClasses class_,Head_T ** head_)155 	void    getHeadOfClass    (eClasses class_, Head_T** head_)
156 	{
157 		if (class_ < CLASS_COUNT) {
158 			objLocks[class_].lock();
159 			*head_ = static_cast<Head_T*>(heads[class_]);
160 			objLocks[class_].unlock();
161 		} else
162 			*head_ = nullptr;
163 	}
164 
165 
166 
167 	/* ----------------------
168 	 * --- Public members ---
169 	 * ----------------------
170 	 */
171 
172 	int32_t     AI_clock              = -1;
173 	BITMAP*     canvas                = nullptr;
174 	const char* client_message        = nullptr; // message sent from client to main menu
175 	PLAYER*     client_player         = nullptr; // the index we use to know which one is the player on the client side
176 	int32_t     curland               = 0;
177 	int32_t     current_drawing_mode  = DRAW_MODE_SOLID;
178 	uint32_t    currentround          = 0;
179 	int32_t     cursky                = 0;
180 	bool        demo_mode             = false;
181 	bool        hasTooMuchDeco        = false; // Set to true if the set FPS are too hard to reach.
182 	BOX*        lastUpdates           = nullptr;
183 	int32_t     lastUpdatesCount      = 0;
184 	double      lastwind              = 0.;
185 	int32_t     naturals_activated    = 0;
186 	int32_t     numTanks              = 0;
187 	TANK*       order[MAXPLAYERS];
188 	bool        showScoreBoard        = false;
189 	bool        skippingComputerPlay  = false;
190 	int32_t     stage                 = STAGE_AIM;
191 	bool        stopwindow            = false;
192 	ai32_t*     surface               = nullptr;
193 	char        tank_status[128];
194 	int32_t     tank_status_colour    = BLACK;
195 	BITMAP*     terrain               = nullptr;
196 	bool        updateMenu            = true;
197 	BOX*        updates               = nullptr;
198 	char*       update_string         = nullptr;
199 	int32_t     used_voices           = 0;
200 	double      wind                  = 0.;
201 
202 
203 private:
204 
205 	typedef sDebrisPool debpool_t;
206 
207 
208 	/* -----------------------
209 	 * --- Private methods ---
210 	 * -----------------------
211 	 */
212 
213 	// Combine make_update and make_bgupdate with safety checks
214 	void addUpdate(int32_t x, int32_t y, int32_t w, int32_t h, BOX* target,
215 	               int32_t &target_count);
216 
217 
218 	/* -----------------------
219 	 * --- Private members ---
220 	 * -----------------------
221 	 */
222 
223 	bool            close_button_pressed = false;
224 	CSpinLock       cbpLock; //[c]lose_[b]utton_[p]ressed
225 	CSpinLock       cmdLock;
226 	bool            combineUpdates       = true;
227 	int32_t         command              = 0;
228 	TANK*           currTank             = nullptr;
229 	debpool_t*      debris_pool          = nullptr;
230 	int8_t*         done                 = nullptr;
231 	double*         dropIncr             = nullptr;
232 	int32_t*        dropTo               = nullptr;
233 	int32_t*        fp                   = nullptr;
234     vobj_t*         heads[CLASS_COUNT];
235 	CSpinLock       landLock;
236 	CSpinLock       objLocks[CLASS_COUNT];
237     vobj_t*         tails[CLASS_COUNT];
238 	int32_t         tankindex            = 0;
239 	int32_t         updateCount          = 0;
240 	double*         velocity             = nullptr;
241 };
242 
243 #define HAS_GLOBALDATA 1
244 
245 #endif
246