1 /**
2 * @file handler_players.cc
3 * @brief players handler
4 * @date 2012-09-05
5 * @copyright 1991-2014 TLK Games
6 * @author Bruno Ethvignot
7 * @version $Revision: 24 $
8 */
9 /*
10 * copyright (c) 1991-2014 TLK Games all rights reserved
11 * $Id: handler_players.cc 24 2014-09-28 15:30:04Z bruno.ethvignot@gmail.com $
12 *
13 * TecnoballZ is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * TecnoballZ is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 * MA 02110-1301, USA.
27 */
28 #include "../include/handler_players.h"
29 #include "../include/controller_gems.h"
30 #include "../include/controller_sides_bricks.h"
31 #include "../include/controller_gems.h"
32
33 Uint32 handler_players::max_of_players = 0;
34 handler_players *handler_players::first_player = NULL;
35 handler_players **handler_players::players_list = NULL;
36
37 /*
38 * Create a player object
39 */
handler_players()40 handler_players::handler_players ()
41 {
42 object_init ();
43
44 /*
45 * add a new player
46 */
47
48 /* first player */
49 if (0 == max_of_players)
50 {
51 first_player = this;
52 next_player = this;
53 previous_player = this;
54 }
55 else
56 {
57 next_player = first_player;
58 handler_players *prev = first_player->get_previous_player ();
59 previous_player = prev;
60 first_player->set_previous_player (this);
61 prev->set_next_player (this);
62 }
63 max_of_players++;
64
65 /*
66 * clear members members
67 */
68 player_num = max_of_players;
69 reset_members ();
70 /* clear name of the player */
71 Uint32 i;
72 for (i = 0; i < 6; i++)
73 {
74 player_name[i] = ' ';
75 }
76 player_name[i] = 0;
77 }
78
79 /*
80 * Release a player object
81 */
~handler_players()82 handler_players::~handler_players ()
83 {
84 max_of_players--;
85 if (max_of_players > 0)
86 {
87 next_player->set_previous_player (previous_player);
88 previous_player->set_next_player (next_player);
89 if (first_player == this)
90 {
91 first_player = next_player;
92 }
93 }
94 else
95 {
96 first_player = NULL;
97 }
98 object_free ();
99 }
100
101 /**
102 * Initialize a player object before a new game
103 * @param lifes number of lifes
104 * @param area area number (1 to 5)
105 * @param level level number in current area (1 to 12)
106 * @param money amount of money
107 * @param grdPt level_list of the guards
108 */
109 void
initialize(Uint32 lifes,Uint32 area,Uint32 level,Uint32 money,Uint32 grdPt)110 handler_players::initialize (Uint32 lifes, Uint32 area, Uint32 level,
111 Uint32 money, Uint32 grdPt)
112 {
113 reset_members ();
114 number_of_lifes = lifes;
115 area_number = area;
116 level_number = level;
117 amount_of_money = money;
118 guardianPt = grdPt;
119 }
120
121 /**
122 * Reset some members values
123 */
124 void
reset_members()125 handler_players::reset_members ()
126 {
127 /* clear the score value of the player */
128 score_value = 0;
129 bonus_life_counter = 0;
130 area_number = 1;
131 //area_number = 5; /*TEST*/
132 /* level number into the current area */
133 level_number = 1;
134 number_of_lifes = initial_num_of_lifes;
135 clear_shopping_cart ();
136 amount_of_money = 500;
137 for (Uint32 i = 0; i < controller_sides_bricks::MAX_OF_SIDES_BRICKS; i++)
138 {
139 map_left_wall[i] = true;
140 map_right_wall[i] = true;
141 map_top_wall[i] = true;
142 }
143 /* disable right, top and left paddles */
144 right_paddle_alive_counter = 0;
145 top_paddle_alive_counter = 0;
146 left_paddle_alive_counter = 0;
147 must_rebuild_walls = false;
148 less_bricks_count = 0;
149 /* width of the horizontal paddles
150 * and height of the vertical paddles */
151 paddle_length = 32 * resolution;
152 budget_prices = false;
153 guardianPt = 0;
154 clear_collected_gems ();
155 }
156
157 /**
158 * Set the player name
159 * @param name the name of the player
160 */
161 void
set_name(const char * name)162 handler_players::set_name (const char *name)
163 {
164 for (Uint32 i = 0; i < PLAYER_NAME_LENGTH; i++)
165 {
166 player_name[i] = ' ';
167 }
168 for (Uint32 i = 0; i < PLAYER_NAME_LENGTH; i++)
169 {
170 char c = name[i];
171 if (0 == c)
172 {
173 return;
174 }
175 if (c >= 'a' && c <= 'z')
176 {
177 c = c - ('a' - 'A');
178 }
179 if ((c >= ' ' && c <= '!') ||
180 (c >= '-' && c <= '.') ||
181 (c >= '0' && c <= ':') || (c >= 'A' && c <= 'Z') || c == '\'')
182 {
183 player_name[i] = c;
184 }
185 else
186 {
187 player_name[i] = ' ';
188 }
189 }
190 }
191
192 /**
193 * Return the current player name
194 * @return the current name the player
195 */
196 char *
get_name()197 handler_players::get_name ()
198 {
199 return &player_name[0];
200 }
201
202 /**
203 * Return the area number
204 * @raturn area number, from 1 to 5
205 */
206 Uint32
get_area_number()207 handler_players::get_area_number ()
208 {
209 return area_number;
210 }
211
212 /**
213 * Return the level number
214 * @return level number, from 1 to 13
215 */
216 Uint32
get_level_number()217 handler_players::get_level_number ()
218 {
219 return level_number;
220 }
221
222 /**
223 * Return the number of life(s)
224 * @return the number of life(s)
225 */
226 Sint32
get_num_of_lifes()227 handler_players::get_num_of_lifes ()
228 {
229 return number_of_lifes;
230 }
231
232 /**
233 * return the paddle's length
234 * @return the length of the paddle in pixels
235 */
236 Uint32
get_paddle_length()237 handler_players::get_paddle_length ()
238 {
239 return paddle_length;
240 }
241
242 /**
243 * Initialize paddle's length
244 * @param length the length of the paddle in pixels
245 */
246 void
set_paddle_length(Uint32 length)247 handler_players::set_paddle_length (Uint32 length)
248 {
249 paddle_length = length;
250 }
251
252 /**
253 * Return the current amount of money
254 * @return the amount of money
255 */
256 Uint32
get_money_amount()257 handler_players::get_money_amount ()
258 {
259 return amount_of_money;
260 }
261
262 /**
263 * Decrease the amount of money
264 * @param value money amount
265 * @return true if the money amount could be descreased
266 */
267 bool
decrease_money_amount(Uint32 value)268 handler_players::decrease_money_amount (Uint32 value)
269 {
270 if (value > amount_of_money)
271 {
272 return false;
273 }
274 amount_of_money -= value;
275 return true;
276 }
277
278 /**
279 * Increase the amount of money
280 * @param value money amount
281 */
282 void
increase_money_amount(Uint32 value)283 handler_players::increase_money_amount (Uint32 value)
284 {
285 amount_of_money += value;
286 }
287
288 /**
289 * Increase the score
290 * @param value is the number of points to increase the score by
291 */
292 void
add_score(Uint32 value)293 handler_players::add_score (Uint32 value)
294 {
295 score_value += value;
296 bonus_life_counter += value;
297 if (bonus_life_counter > 25000)
298 {
299 add_life (1);
300 bonus_life_counter -= 25000;
301 }
302 }
303
304 /**
305 * Clear the shopping cart
306 */
307 void
clear_shopping_cart()308 handler_players::clear_shopping_cart ()
309 {
310 Sint32 *cart = shopping_cart;
311 for (Uint32 i = 0; i < supervisor_shop::MAX_OF_CAPSULES_BOUGHT; i++)
312 {
313 *(cart++) = 0;
314 }
315 /* clear the number of items bought */
316 shopping_cart_items = 0;
317 /* end of the shopping cart */
318 *cart = -1;
319 }
320
321 /**
322 * Return the list of items bought in th shop
323 * @return a pointer to the list of itemps bought in th shop
324 */
325 Sint32 *
get_shopping_cart()326 handler_players::get_shopping_cart ()
327 {
328 return shopping_cart;
329 }
330
331 /**
332 * Return the number of itemp bought in th shop
333 * @return the number of items bought in th shop
334 */
335 Uint32
get_numof_items_in_shopping_cart()336 handler_players::get_numof_items_in_shopping_cart ()
337 {
338 return shopping_cart_items;
339 }
340
341 /**
342 * Set the number of items bought
343 * @param count Number of items
344 */
345 void
set_numof_items_in_shopping_cart(Uint32 count)346 handler_players::set_numof_items_in_shopping_cart (Uint32 count)
347 {
348 shopping_cart_items = count;
349 }
350
351 /**
352 * Clear the list of gems collected
353 */
354 void
clear_collected_gems()355 handler_players::clear_collected_gems ()
356 {
357 for (Uint32 i = 0; i < controller_gems::MAX_OF_GEMS; i++)
358 {
359 /* states of the 6 gems */
360 gems_state_list[i] = false;
361 }
362 }
363
364 /**
365 * Verify if the 6 gemstones are collected
366 * @param gem_id last gem identifier collected
367 * @return true if all gems are collected, otherwise false
368 */
369 bool
are_collected_all_gems(Uint32 gemNu)370 handler_players::are_collected_all_gems (Uint32 gemNu)
371 {
372 gems_state_list[gemNu] = true;
373 for (Uint32 i = 0; i < controller_gems::MAX_OF_GEMS; i++)
374 {
375 if (!gems_state_list[i])
376 {
377 return false;
378 }
379 }
380 clear_collected_gems ();
381 return true;
382 }
383
384 /**
385 * Return state of one of six gemstones
386 * @param gem_id gem identifier 0 to 5
387 * @return true if the gem is enabled, otherwise false
388 */
389 bool
is_collected_gem(Uint32 gem_id)390 handler_players::is_collected_gem (Uint32 gem_id)
391 {
392 return gems_state_list[gem_id];
393 }
394
395 /**
396 * Get the alive counter of a paddle
397 * @param paddle_num paddle number RIGHT_PADDLE, TOP_PADDLE, or LEFT_PADDLE
398 * @return alive counter value, if 0 then the paddle is disabled
399 */
400 Uint32
get_paddle_alive_counter(Uint32 paddle_num)401 handler_players::get_paddle_alive_counter (Uint32 paddle_num)
402 {
403 switch (paddle_num)
404 {
405 case controller_paddles::RIGHT_PADDLE:
406 return right_paddle_alive_counter;
407 break;
408 case controller_paddles::TOP_PADDLE:
409 return top_paddle_alive_counter;
410 break;
411 default:
412 return left_paddle_alive_counter;
413 break;
414 }
415 }
416
417 /**
418 * Set the alive counter of a paddle
419 * @param paddle_num paddle number RIGHT_PADDLE, TOP_PADDLE, or LEFT_PADDLE
420 * @param count value of the counter, if 0 then the paddle is disabled
421 */
422 void
set_paddle_alive_counter(Uint32 paddle_num,Uint32 counter)423 handler_players::set_paddle_alive_counter (Uint32 paddle_num, Uint32 counter)
424 {
425 switch (paddle_num)
426 {
427 case controller_paddles::RIGHT_PADDLE:
428 right_paddle_alive_counter = counter;
429 break;
430 case controller_paddles::TOP_PADDLE:
431 top_paddle_alive_counter = counter;
432 break;
433 case controller_paddles::LEFT_PADDLE:
434 left_paddle_alive_counter = counter;
435 break;
436 }
437 }
438
439 /**
440 * Initialize less bricks option
441 * @param count number of bricks in less
442 */
443 void
set_less_bricks(Uint32 count)444 handler_players::set_less_bricks (Uint32 count)
445 {
446 less_bricks_count = count;
447 }
448
449 /**
450 * Return number of bricks in less
451 * @return number of bricks in less
452 */
453 Uint32
get_less_bricks()454 handler_players::get_less_bricks ()
455 {
456 return less_bricks_count;
457 }
458
459 /**
460 * Set the budget prices option
461 * @param enable true if enable the budget prices option, false otherwise
462 */
463 void
set_budget_prices(bool enable)464 handler_players::set_budget_prices (bool enable)
465 {
466 budget_prices = enable;
467 }
468
469 /**
470 * Check if the budget prices option is enable
471 */
472 bool
is_budget_prices()473 handler_players::is_budget_prices ()
474 {
475 return budget_prices;
476 }
477
478 /**
479 * Enable or disable the option which will rebuild the walls bricks
480 * on the next levels
481 * @param enable true if rebuilt the walls, false otherwise
482 */
483 void
set_rebuild_walls(bool enable)484 handler_players::set_rebuild_walls (bool enable)
485 {
486 must_rebuild_walls = enable;
487 }
488
489 /**
490 * Check if the walls must be rebuilt.
491 * @return true if rebuilt the walls, false otherwise
492 */
493 bool
is_rebuild_walls()494 handler_players::is_rebuild_walls ()
495 {
496 return must_rebuild_walls;
497 }
498
499 /**
500 * Return state of the left wall bricks
501 * @return a pointer to the map of the left wall
502 */
503 bool *
get_map_left()504 handler_players::get_map_left ()
505 {
506 return map_left_wall;
507 }
508
509 /**
510 * Return state of the right wall bricks
511 * @return a pointer to the map of the right wall
512 */
513 bool *
get_map_right()514 handler_players::get_map_right ()
515 {
516 return map_right_wall;
517 }
518
519 /**
520 * Return state of the top wall bricks
521 * @return a pointer to the map of the top wall
522 */
523 bool *
get_map_top()524 handler_players::get_map_top ()
525 {
526 return map_top_wall;
527 }
528
529 //-----------------------------------------------------------------------------
530 // is the lastest level of tecnoballz?
531 // output <= 1: end of game :-)
532 //-----------------------------------------------------------------------------
533 Sint32
zlastlevel()534 handler_players::zlastlevel ()
535 {
536 if (area_number >= 5 && level_number >= 13)
537 return 1;
538 else
539 return 0;
540 }
541
542 //-----------------------------------------------------------------------------
543 // next level
544 // output <= 1: end of game :-)
545 //-----------------------------------------------------------------------------
546 Sint32
next_level(Sint32 grdNx)547 handler_players::next_level (Sint32 grdNx)
548 {
549 Sint32 r = 0;
550 if (is_verbose)
551 printf
552 ("handler_players::next_level() area_number=%i, level_number=%i grdNx=%i guardianPt =%i\n",
553 area_number, level_number, grdNx, guardianPt);
554 if (area_number == 5 && level_number == 13)
555 {
556 area_number = 1;
557 level_number = 1;
558 r = 1; //end of game
559 guardianPt = 0;
560 }
561 else
562 {
563 if (area_number == 5 && level_number == 12)
564 {
565 level_number++;
566 guardianPt += grdNx;
567 }
568 else
569 {
570 level_number++;
571 if (level_number == 13)
572 {
573 area_number++;
574 level_number = 1;
575 guardianPt += grdNx;
576 }
577 if (level_number == 7)
578 guardianPt += grdNx;
579 }
580 }
581 if (is_verbose)
582 printf
583 ("handler_players::next_level() area_number=%i, level_number=%i, guardianPt=%i\n",
584 area_number, level_number, guardianPt);
585 return r;
586 }
587
588 /**
589 * Return the phase code
590 * @return the next phase code GUARDS_LEVEL or SHOP
591 */
592 Uint32
get_next_phase()593 handler_players::get_next_phase ()
594 {
595 /* MAIN_MENU is a very improbable case */
596 Uint32 phase = MAIN_MENU;
597 /* levels 6, 12 and the level 13 of the area 5 are guardians levels */
598 if (level_number == 6 || level_number == 12 || level_number == 13)
599 {
600 phase = GUARDS_LEVEL;
601 }
602 else
603 {
604 /* before a level, there is always the shop,
605 * except for the first level of the first area */
606 if (level_number > 0 && level_number < 12)
607 {
608 phase = SHOP;
609 }
610 }
611 return phase;
612 }
613
614 /**
615 * Return previous player
616 * @return a pointer to the previous player object
617 */
618 handler_players *
get_previous_player()619 handler_players::get_previous_player ()
620 {
621 return previous_player;
622 }
623
624 /**
625 * Set the next player
626 * @param player pointer to a object player
627 */
628 void
set_next_player(handler_players * player)629 handler_players::set_next_player (handler_players * player)
630 {
631 next_player = player;
632 }
633
634 /**
635 * Get the previous player
636 * @param player pointer to a object player
637 */
638 void
set_previous_player(handler_players * player)639 handler_players::set_previous_player (handler_players * player)
640 {
641 previous_player = player;
642 }
643
644 //-----------------------------------------------------------------------------
645 // get pointer to "level_list" of the guards
646 //-----------------------------------------------------------------------------
647 Sint32
getGuardPt()648 handler_players::getGuardPt ()
649 {
650 return guardianPt;
651 }
652
653 //-----------------------------------------------------------------------------
654 // set pointer to "level_list" of the guards
655 //-----------------------------------------------------------------------------
656 void
setGuardPt(Sint32 grdPt)657 handler_players::setGuardPt (Sint32 grdPt)
658 {
659 guardianPt = grdPt;
660 }
661
662 /**
663 * Add one or more lifes
664 * @param add number of lifes to add
665 */
666 void
add_life(Uint32 add)667 handler_players::add_life (Uint32 add)
668 {
669 number_of_lifes += add;
670 }
671
672 /**
673 * Remove one or more lifes
674 * @param add number of lifes to remove
675 */
676 void
remove_life(Uint32 remove)677 handler_players::remove_life (Uint32 remove)
678 {
679 number_of_lifes -= remove;
680 if (number_of_lifes < 0)
681 {
682 number_of_lifes = 0;
683 }
684 }
685
686 /**
687 * Remove all lifes, when the game over is forced
688 */
689 void
remove_all_lifes()690 handler_players::remove_all_lifes ()
691 {
692 number_of_lifes = 0;
693 }
694
695 /*
696 * Statics methods
697 */
698
699 /**
700 * Static method which return next player and determine the next phase
701 * @param player the current "handler_players" object
702 * @param next_phase pointer to "end_return"
703 * @param grdNx pointer to "level_list" of the guards (NULL by default)
704 * @return the new player object
705 */
706 handler_players *
get_next_player(handler_players * player,Uint32 * next_phase,Sint32 grdNx)707 handler_players::get_next_player (handler_players * player, Uint32 * next_phase,
708 Sint32 grdNx)
709 {
710 Uint32 start = player->player_num;
711 Uint32 index = start;
712 if (current_phase != SHOP)
713 {
714 /* jump to the next level */
715 player->next_level (grdNx);
716 }
717
718 /* process each player object */
719 for (Uint32 i = 0; i < max_of_players; i++)
720 {
721 if (++index > max_of_players)
722 {
723 index = 1;
724 }
725 handler_players *player = players_list[index - 1];
726 if (player->number_of_lifes <= 0)
727 {
728 continue;
729 }
730 /* get next phase: GUARDS_LEVEL or SHOP */
731 *next_phase = player->get_next_phase ();
732
733 /* this player already went to the shop,
734 * he jump to the bricks level */
735 if (player->player_num <= start && *next_phase == SHOP
736 && current_phase == SHOP)
737 {
738 *next_phase = BRICKS_LEVEL;
739 }
740 /* multiplayers case: all players play the same level */
741 if (player->player_num > start && current_phase != SHOP
742 && *next_phase == SHOP)
743 {
744 *next_phase = BRICKS_LEVEL;
745 }
746 return player;
747 }
748 /* unlikely case */
749 *next_phase = MAIN_MENU;
750 return players_list[0];
751 }
752
753 /**
754 * Static method which initializes the maximum number of players
755 * @param numof maximum number of players, always 6
756 */
757 handler_players *
create_all_players(Uint32 numof)758 handler_players::create_all_players (Uint32 numof)
759 {
760
761 try
762 {
763 players_list = new handler_players *[numof];
764 }
765 catch (std::bad_alloc &)
766 {
767 std::
768 cerr << "(!)handler_players::joueursADD() "
769 "not enough memory to allocate " <<
770 numof << " list elements!" << std::endl;
771 throw;
772 }
773
774 /* create the players objects */
775 for (Uint32 i = 0; i < numof; i++)
776 {
777 players_list[i] = new handler_players ();
778 }
779 return first_player;
780 }
781
782 /**
783 * Static method which releases all objects players
784 */
785 void
release_all_players()786 handler_players::release_all_players ()
787 {
788 for (Uint32 i = 0; i < max_of_players; i++)
789 {
790 delete first_player;
791 }
792 if (NULL != players_list)
793 {
794 delete[]players_list;
795 players_list = NULL;
796 }
797 }
798