webperimental: killstack decides stack protects.
[freeciv.git] / server / voting.c
blobbeaaa9149dff23ba864728b18e89796f2d614a1a
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <math.h>
20 /* utility */
21 #include "fcintl.h"
22 #include "log.h"
23 #include "support.h"
25 /* common */
26 #include "capability.h"
27 #include "connection.h"
28 #include "packets.h"
29 #include "player.h"
31 /* server */
32 #include "commands.h"
33 #include "console.h"
34 #include "hand_gen.h"
35 #include "notify.h"
36 #include "settings.h"
37 #include "stdinhand.h"
39 #include "voting.h"
41 struct vote_list *vote_list = NULL;
42 int vote_number_sequence = 0;
45 /**************************************************************************
46 Helper function that returns the current number of eligible voters.
47 **************************************************************************/
48 int count_voters(const struct vote *pvote)
50 int num_voters = 0;
52 conn_list_iterate(game.est_connections, pconn) {
53 if (conn_can_vote(pconn, pvote)) {
54 num_voters++;
56 } conn_list_iterate_end;
58 return num_voters;
61 /**************************************************************************
62 Tell clients that a new vote has been created.
63 **************************************************************************/
64 static void lsend_vote_new(struct conn_list *dest, struct vote *pvote)
66 struct packet_vote_new packet;
67 struct connection *pconn;
69 if (pvote == NULL) {
70 return;
73 pconn = conn_by_number(pvote->caller_id);
74 if (pconn == NULL) {
75 return;
78 log_debug("lsend_vote_new %p (%d) --> %p", pvote, pvote->vote_no, dest);
80 packet.vote_no = pvote->vote_no;
81 sz_strlcpy(packet.user, pconn->username);
82 describe_vote(pvote, packet.desc, sizeof(packet.desc));
84 packet.percent_required = 100 * pvote->need_pc;
85 packet.flags = pvote->flags;
87 if (dest == NULL) {
88 dest = game.est_connections;
91 conn_list_iterate(dest, conn) {
92 if (!conn_can_see_vote(conn, pvote)) {
93 continue;
95 send_packet_vote_new(conn, &packet);
96 } conn_list_iterate_end;
99 /**************************************************************************
100 Send updated status information about the given vote.
101 **************************************************************************/
102 static void lsend_vote_update(struct conn_list *dest, struct vote *pvote,
103 int num_voters)
105 struct packet_vote_update packet;
106 struct connection *pconn;
108 if (pvote == NULL) {
109 return;
112 pconn = conn_by_number(pvote->caller_id);
113 if (pconn == NULL) {
114 return;
117 log_debug("lsend_vote_update %p (%d) --> %p", pvote, pvote->vote_no, dest);
119 packet.vote_no = pvote->vote_no;
120 packet.yes = pvote->yes;
121 packet.no = pvote->no;
122 packet.abstain = pvote->abstain;
123 packet.num_voters = num_voters;
125 if (dest == NULL) {
126 dest = game.est_connections;
129 conn_list_iterate(dest, aconn) {
130 if (!conn_can_see_vote(aconn, pvote)) {
131 continue;
133 send_packet_vote_update(aconn, &packet);
134 } conn_list_iterate_end;
137 /**************************************************************************
138 Tell clients that the given vote no longer exists.
139 **************************************************************************/
140 static void lsend_vote_remove(struct conn_list *dest, struct vote *pvote)
142 struct packet_vote_remove packet;
144 if (!pvote) {
145 return;
148 packet.vote_no = pvote->vote_no;
150 if (dest == NULL) {
151 dest = game.est_connections;
154 conn_list_iterate(dest, pconn) {
155 send_packet_vote_remove(pconn, &packet);
156 } conn_list_iterate_end;
159 /**************************************************************************
160 Tell clients that the given vote resolved.
161 **************************************************************************/
162 static void lsend_vote_resolve(struct conn_list *dest,
163 struct vote *pvote, bool passed)
165 struct packet_vote_resolve packet;
167 if (!pvote) {
168 return;
171 packet.vote_no = pvote->vote_no;
172 packet.passed = passed;
174 if (dest == NULL) {
175 dest = game.est_connections;
178 conn_list_iterate(dest, pconn) {
179 if (!conn_can_see_vote(pconn, pvote)) {
180 continue;
182 send_packet_vote_resolve(pconn, &packet);
183 } conn_list_iterate_end;
186 /**************************************************************************
187 Free all memory used by the vote structure.
188 **************************************************************************/
189 static void free_vote(struct vote *pvote)
191 if (!pvote) {
192 return;
195 vote_cast_list_iterate(pvote->votes_cast, pvc) {
196 free(pvc);
197 } vote_cast_list_iterate_end;
198 vote_cast_list_destroy(pvote->votes_cast);
199 free(pvote);
202 /**************************************************************************
203 Remove the given vote and send a vote_remove packet to clients.
204 **************************************************************************/
205 void remove_vote(struct vote *pvote)
207 if (!vote_list || !pvote) {
208 return;
211 vote_list_remove(vote_list, pvote);
212 lsend_vote_remove(NULL, pvote);
213 free_vote(pvote);
216 /**************************************************************************
217 Remove all votes. Sends vote_remove packets to clients.
218 **************************************************************************/
219 void clear_all_votes(void)
221 if (!vote_list) {
222 return;
225 vote_list_iterate(vote_list, pvote) {
226 lsend_vote_remove(NULL, pvote);
227 free_vote(pvote);
228 } vote_list_iterate_end;
229 vote_list_clear(vote_list);
232 /***************************************************************************
233 Returns TRUE if this vote is a "teamvote".
234 ***************************************************************************/
235 bool vote_is_team_only(const struct vote *pvote)
237 return pvote && (pvote->flags & VCF_TEAMONLY);
240 /***************************************************************************
241 A user cannot vote if:
242 * is not connected
243 * access level < basic
244 * isn't a player
245 * the vote is a team vote and not on the caller's team
246 NB: If 'pvote' is NULL, then the team condition is not checked.
247 ***************************************************************************/
248 bool conn_can_vote(const struct connection *pconn, const struct vote *pvote)
250 if (!pconn || !conn_controls_player(pconn)
251 || conn_get_access(pconn) < ALLOW_BASIC) {
252 return FALSE;
255 if (vote_is_team_only(pvote)) {
256 const struct player *pplayer, *caller_plr;
258 pplayer = conn_get_player(pconn);
259 caller_plr = conn_get_player(vote_get_caller(pvote));
260 if (!pplayer || !caller_plr
261 || !players_on_same_team(pplayer, caller_plr)) {
262 return FALSE;
266 return TRUE;
269 /***************************************************************************
270 Usually, all users can see, except in the team vote case.
271 ***************************************************************************/
272 bool conn_can_see_vote(const struct connection *pconn,
273 const struct vote *pvote)
275 if (!pconn) {
276 return FALSE;
279 if (conn_is_global_observer(pconn)) {
280 /* All is visible for global observer. */
281 return TRUE;
284 if (vote_is_team_only(pvote)) {
285 const struct player *pplayer, *caller_plr;
287 pplayer = conn_get_player(pconn);
288 caller_plr = conn_get_player(vote_get_caller(pvote));
289 if (!pplayer || !caller_plr
290 || !players_on_same_team(pplayer, caller_plr)) {
291 return FALSE;
295 return TRUE;
298 /**************************************************************************
299 Returns the vote with vote number 'vote_no', or NULL.
300 **************************************************************************/
301 struct vote *get_vote_by_no(int vote_no)
303 if (!vote_list) {
304 return NULL;
307 vote_list_iterate(vote_list, pvote) {
308 if (pvote->vote_no == vote_no) {
309 return pvote;
311 } vote_list_iterate_end;
313 return NULL;
316 /**************************************************************************
317 Returns the vote called by 'caller', or NULL if none exists.
318 **************************************************************************/
319 struct vote *get_vote_by_caller(const struct connection *caller)
321 if (caller == NULL || !vote_list) {
322 return NULL;
325 vote_list_iterate(vote_list, pvote) {
326 if (pvote->caller_id == caller->id) {
327 return pvote;
329 } vote_list_iterate_end;
331 return NULL;
334 /**************************************************************************
335 Create and return a newly allocated vote for the command with id
336 'command_id' and all arguments in the string 'allargs'.
337 **************************************************************************/
338 struct vote *vote_new(struct connection *caller,
339 const char *allargs,
340 int command_id)
342 struct vote *pvote;
343 const struct command *pcmd;
345 if (!conn_can_vote(caller, NULL)) {
346 return NULL;
349 /* Cancel previous vote */
350 remove_vote(get_vote_by_caller(caller));
352 /* Make a new vote */
353 pvote = fc_malloc(sizeof(struct vote));
354 pvote->caller_id = caller->id;
355 pvote->command_id = command_id;
356 pcmd = command_by_number(command_id);
358 sz_strlcpy(pvote->cmdline, command_name(pcmd));
359 if (allargs != NULL && allargs[0] != '\0') {
360 sz_strlcat(pvote->cmdline, " ");
361 sz_strlcat(pvote->cmdline, allargs);
364 pvote->turn_count = 0;
365 pvote->votes_cast = vote_cast_list_new();
366 pvote->vote_no = ++vote_number_sequence;
368 vote_list_append(vote_list, pvote);
370 pvote->flags = command_vote_flags(pcmd);
371 pvote->need_pc = (double) command_vote_percent(pcmd) / 100.0;
373 if (pvote->flags & VCF_NOPASSALONE) {
374 int num_voters = count_voters(pvote);
375 double min_pc = 1.0 / (double) num_voters;
377 if (num_voters > 1 && min_pc > pvote->need_pc) {
378 pvote->need_pc = MIN(0.5, 2.0 * min_pc);
382 lsend_vote_new(NULL, pvote);
384 return pvote;
387 /****************************************************************************
388 Return whether the vote would pass immediately when the caller will vote
389 for.
390 ****************************************************************************/
391 bool vote_would_pass_immediately(const struct connection *caller,
392 int command_id)
394 struct vote virtual_vote;
395 const struct command *pcmd;
397 if (!conn_can_vote(caller, NULL)) {
398 return FALSE;
401 pcmd = command_by_number(command_id);
402 fc_assert(pcmd != NULL);
403 memset(&virtual_vote, 0, sizeof(virtual_vote));
404 virtual_vote.flags = command_vote_flags(pcmd);
406 if (virtual_vote.flags & VCF_NOPASSALONE) {
407 return FALSE;
410 virtual_vote.caller_id = caller->id;
411 return (((double) (command_vote_percent(pcmd)
412 * count_voters(&virtual_vote)) / 100.0) < 1.0);
415 /**************************************************************************
416 Check if we satisfy the criteria for resolving a vote, and resolve it
417 if these critera are indeed met. Updates yes and no variables in voting
418 struct as well.
419 **************************************************************************/
420 static void check_vote(struct vote *pvote)
422 int num_cast = 0, num_voters = 0;
423 bool resolve = FALSE, passed = FALSE;
424 struct connection *pconn = NULL;
425 double yes_pc = 0.0, no_pc = 0.0, rem_pc = 0.0, base = 0.0;
426 int flags;
427 double need_pc;
428 char cmdline[MAX_LEN_CONSOLE_LINE];
429 const double MY_EPSILON = 0.000001;
430 const char *title;
431 const struct player *callplr;
433 if (!pvote) {
434 return;
437 pvote->yes = 0;
438 pvote->no = 0;
439 pvote->abstain = 0;
441 num_voters = count_voters(pvote);
443 vote_cast_list_iterate(pvote->votes_cast, pvc) {
444 if (!(pconn = conn_by_number(pvc->conn_id))
445 || !conn_can_vote(pconn, pvote)) {
446 continue;
448 num_cast++;
450 switch (pvc->vote_cast) {
451 case VOTE_YES:
452 pvote->yes++;
453 continue;
454 case VOTE_NO:
455 pvote->no++;
456 continue;
457 case VOTE_ABSTAIN:
458 pvote->abstain++;
459 continue;
460 case VOTE_NUM:
461 break;
464 log_error("Unknown vote cast variant: %d.", pvc->vote_cast);
465 pvote->abstain++;
466 } vote_cast_list_iterate_end;
468 flags = pvote->flags;
469 need_pc = pvote->need_pc;
471 /* Check if we should resolve the vote. */
472 if (num_voters > 0) {
474 /* Players that abstain essentially remove themselves from
475 * the voting pool. */
476 base = num_voters - pvote->abstain;
478 if (base > MY_EPSILON) {
479 yes_pc = (double) pvote->yes / base;
480 no_pc = (double) pvote->no / base;
482 /* The fraction of people who have not voted at all. */
483 rem_pc = (double) (num_voters - num_cast) / base;
486 if (flags & VCF_NODISSENT && no_pc > MY_EPSILON) {
487 resolve = TRUE;
490 if (!resolve) {
491 resolve = (/* We have enough yes votes. */
492 (yes_pc - need_pc > MY_EPSILON)
493 /* We have too many no votes. */
494 || (no_pc - 1.0 + need_pc > MY_EPSILON
495 || fabs(no_pc - 1.0 + need_pc) < MY_EPSILON)
496 /* We can't get enough no votes. */
497 || (no_pc + rem_pc - 1.0 + need_pc < -MY_EPSILON)
498 /* We can't get enough yes votes. */
499 || (yes_pc + rem_pc - need_pc < -MY_EPSILON
500 || fabs(yes_pc + rem_pc - need_pc) < MY_EPSILON));
503 /* Resolve if everyone voted already. */
504 if (!resolve && fabs(rem_pc) < MY_EPSILON) {
505 resolve = TRUE;
508 /* Resolve this vote if it has been around long enough. */
509 if (!resolve && pvote->turn_count > 1) {
510 resolve = TRUE;
513 /* Resolve this vote if everyone tries to abstain. */
514 if (!resolve && fabs(base) < MY_EPSILON) {
515 resolve = TRUE;
519 log_debug("check_vote flags=%d need_pc=%0.2f yes_pc=%0.2f "
520 "no_pc=%0.2f rem_pc=%0.2f base=%0.2f resolve=%d",
521 flags, need_pc, yes_pc, no_pc, rem_pc, base, resolve);
523 lsend_vote_update(NULL, pvote, num_voters);
525 if (!resolve) {
526 return;
529 passed = yes_pc - need_pc > MY_EPSILON;
531 if (passed && flags & VCF_NODISSENT) {
532 passed = fabs(no_pc) < MY_EPSILON;
535 if (vote_is_team_only(pvote)) {
536 const struct connection *caller;
538 /* TRANS: "Vote" as a process. Used as part of a sentence. */
539 title = _("Teamvote");
540 caller = vote_get_caller(pvote);
541 callplr = conn_get_player(caller);
542 } else {
543 /* TRANS: "Vote" as a process. Used as part of a sentence. */
544 title = _("Vote");
545 callplr = NULL;
548 if (passed) {
549 notify_team(callplr, NULL, E_VOTE_RESOLVED, ftc_vote_passed,
550 /* TRANS: "[Vote|Teamvote] 3 \"proposed change\" is ..." */
551 _("%s %d \"%s\" is passed %d to %d with "
552 "%d abstentions and %d who did not vote."),
553 title, pvote->vote_no, pvote->cmdline, pvote->yes,
554 pvote->no, pvote->abstain, num_voters - num_cast);
555 } else {
556 notify_team(callplr, NULL, E_VOTE_RESOLVED, ftc_vote_failed,
557 /* TRANS: "[Vote|Teamvote] 3 \"proposed change\" failed ..." */
558 _("%s %d \"%s\" failed with %d against, %d for, "
559 "%d abstentions and %d who did not vote."),
560 title, pvote->vote_no, pvote->cmdline, pvote->no,
561 pvote->yes, pvote->abstain, num_voters - num_cast);
564 lsend_vote_resolve(NULL, pvote, passed);
566 vote_cast_list_iterate(pvote->votes_cast, pvc) {
567 if (!(pconn = conn_by_number(pvc->conn_id))) {
568 log_error("Got a vote from a lost connection");
569 continue;
570 } else if (!conn_can_vote(pconn, pvote)) {
571 log_error("Got a vote from a non-voting connection");
572 continue;
575 switch (pvc->vote_cast) {
576 case VOTE_YES:
577 notify_team(callplr, NULL, E_VOTE_RESOLVED, ftc_vote_yes,
578 _("%s %d: %s voted yes."),
579 title, pvote->vote_no, pconn->username);
580 break;
581 case VOTE_NO:
582 notify_team(callplr, NULL, E_VOTE_RESOLVED, ftc_vote_no,
583 _("%s %d: %s voted no."),
584 title, pvote->vote_no, pconn->username);
585 break;
586 case VOTE_ABSTAIN:
587 notify_team(callplr, NULL, E_VOTE_RESOLVED, ftc_vote_abstain,
588 _("%s %d: %s chose to abstain."),
589 title, pvote->vote_no, pconn->username);
590 break;
591 default:
592 break;
594 } vote_cast_list_iterate_end;
596 /* Remove the vote before executing the command because it's the
597 * cause of many crashes due to the /cut command:
598 * - If the caller is the target.
599 * - If the target votes on this vote. */
600 sz_strlcpy(cmdline, pvote->cmdline);
601 remove_vote(pvote);
603 if (passed) {
604 handle_stdin_input(NULL, cmdline);
608 /**************************************************************************
609 Find the vote cast for the user id conn_id in a vote.
610 **************************************************************************/
611 static struct vote_cast *vote_cast_find(struct vote *pvote, int conn_id)
613 if (!pvote) {
614 return NULL;
617 vote_cast_list_iterate(pvote->votes_cast, pvc) {
618 if (pvc->conn_id == conn_id) {
619 return pvc;
621 } vote_cast_list_iterate_end;
623 return NULL;
626 /**************************************************************************
627 Return a new vote cast.
628 **************************************************************************/
629 static struct vote_cast *vote_cast_new(struct vote *pvote)
631 struct vote_cast *pvc;
633 if (!pvote) {
634 return NULL;
637 pvc = fc_malloc(sizeof(struct vote_cast));
638 pvc->conn_id = -1;
639 pvc->vote_cast = VOTE_ABSTAIN;
641 vote_cast_list_append(pvote->votes_cast, pvc);
643 return pvc;
646 /**************************************************************************
647 Remove a vote cast. This unlinks it and frees its memory.
648 **************************************************************************/
649 static void remove_vote_cast(struct vote *pvote, struct vote_cast *pvc)
651 if (!pvote || !pvc) {
652 return;
655 vote_cast_list_remove(pvote->votes_cast, pvc);
656 free(pvc);
657 check_vote(pvote); /* Maybe can pass */
660 /**************************************************************************
661 Make the given connection vote 'type' on 'pvote', and check the vote.
662 **************************************************************************/
663 void connection_vote(struct connection *pconn,
664 struct vote *pvote,
665 enum vote_type type)
667 struct vote_cast *pvc;
669 if (!conn_can_vote(pconn, pvote)) {
670 return;
673 /* Try to find a previous vote */
674 if ((pvc = vote_cast_find(pvote, pconn->id))) {
675 pvc->vote_cast = type;
676 } else if ((pvc = vote_cast_new(pvote))) {
677 pvc->vote_cast = type;
678 pvc->conn_id = pconn->id;
679 } else {
680 /* Must never happen */
681 log_error("Failed to create a vote cast for connection %s.",
682 pconn->username);
683 return;
685 check_vote(pvote);
688 /**************************************************************************
689 Cancel the votes of a lost or a detached connection.
690 **************************************************************************/
691 void cancel_connection_votes(struct connection *pconn)
693 if (!pconn || !vote_list) {
694 return;
697 remove_vote(get_vote_by_caller(pconn));
699 vote_list_iterate(vote_list, pvote) {
700 remove_vote_cast(pvote, vote_cast_find(pvote, pconn->id));
701 } vote_list_iterate_end;
704 /**************************************************************************
705 Initialize data structures used by this module.
706 **************************************************************************/
707 void voting_init(void)
709 if (!vote_list) {
710 vote_list = vote_list_new();
711 vote_number_sequence = 0;
715 /**************************************************************************
716 Check running votes. This should be called every turn.
717 **************************************************************************/
718 void voting_turn(void)
720 if (!vote_list) {
721 log_error("voting_turn() called before voting_init()");
722 return;
725 vote_list_iterate(vote_list, pvote) {
726 pvote->turn_count++;
727 check_vote(pvote);
728 } vote_list_iterate_end;
731 /**************************************************************************
732 Free all memory used by this module.
733 **************************************************************************/
734 void voting_free(void)
736 clear_all_votes();
737 if (vote_list) {
738 vote_list_destroy(vote_list);
739 vote_list = NULL;
743 /**************************************************************************
744 Fills the supplied buffer with a string describing the given vote. This
745 includes the vote command line, the percent required to pass, and any
746 special conditions.
747 **************************************************************************/
748 int describe_vote(struct vote *pvote, char *buf, int buflen)
750 int ret = 0;
752 /* NB We don't handle votes with multiple flags here. */
754 if (pvote->flags & VCF_NODISSENT) {
755 ret = fc_snprintf(buf, buflen,
756 /* TRANS: Describing a new vote that can only pass
757 * if there are no dissenting votes. */
758 _("%s (needs %0.0f%% and no dissent)."),
759 pvote->cmdline, MIN(100.0, pvote->need_pc * 100.0 + 1));
760 } else {
761 ret = fc_snprintf(buf, buflen,
762 /* TRANS: Describing a new vote that can pass only if the
763 * given percentage of players votes 'yes'. */
764 _("%s (needs %0.0f%% in favor)."),
765 pvote->cmdline, MIN(100.0, pvote->need_pc * 100.0 + 1));
768 return ret;
771 /**************************************************************************
772 Handle a vote submit packet sent from a client. This is basically just
773 a Wrapper around connection_vote().
774 **************************************************************************/
775 void handle_vote_submit(struct connection *pconn, int vote_no, int value)
777 struct vote *pvote;
778 enum vote_type type;
780 log_debug("Got vote submit (%d %d) from %s.",
781 vote_no, value, conn_description(pconn));
783 pvote = get_vote_by_no(vote_no);
784 if (pvote == NULL) {
785 /* The client is out of synchronization: this vote is probably just
786 * resolved or cancelled. Not an error, let's just ignore the packet. */
787 log_verbose("Submit request for unknown vote_no %d from %s ignored.",
788 vote_no, conn_description(pconn));
789 return;
792 if (value == 1) {
793 type = VOTE_YES;
794 } else if (value == -1) {
795 type = VOTE_NO;
796 } else if (value == 0) {
797 type = VOTE_ABSTAIN;
798 } else {
799 log_error("Invalid packet data for submit of vote %d "
800 "from %s ignored.", vote_no, conn_description(pconn));
801 return;
804 connection_vote(pconn, pvote, type);
807 /****************************************************************************
808 Sends a packet_vote_new to pconn for every currently running votes.
809 ****************************************************************************/
810 void send_running_votes(struct connection *pconn, bool only_team_votes)
812 if (NULL == vote_list
813 || vote_list_size(vote_list) < 1
814 || NULL == pconn
815 || (only_team_votes && NULL == conn_get_player(pconn))) {
816 return;
819 log_debug("Sending %s running votes to %s.",
820 only_team_votes ? "team" : "all", conn_description(pconn));
822 connection_do_buffer(pconn);
823 vote_list_iterate(vote_list, pvote) {
824 if (vote_is_team_only(pvote)) {
825 if (conn_can_see_vote(pconn, pvote)) {
826 lsend_vote_new(pconn->self, pvote);
827 lsend_vote_update(pconn->self, pvote, count_voters(pvote));
829 } else if (!only_team_votes) {
830 lsend_vote_new(pconn->self, pvote);
831 lsend_vote_update(pconn->self, pvote, count_voters(pvote));
833 } vote_list_iterate_end;
834 connection_do_unbuffer(pconn);
837 /****************************************************************************
838 Sends a packet_vote_remove to pconn for every currently running team vote
839 'pconn' can see.
840 ****************************************************************************/
841 void send_remove_team_votes(struct connection *pconn)
843 if (NULL == vote_list
844 || vote_list_size(vote_list) < 1
845 || NULL == pconn
846 || NULL == conn_get_player(pconn)) {
847 return;
850 log_debug("Sending remove info of the team votes to %s.",
851 conn_description(pconn));
853 connection_do_buffer(pconn);
854 vote_list_iterate(vote_list, pvote) {
855 if (vote_is_team_only(pvote) && conn_can_see_vote(pconn, pvote)) {
856 lsend_vote_remove(pconn->self, pvote);
858 } vote_list_iterate_end;
859 connection_do_unbuffer(pconn);
862 /**************************************************************************
863 Sends a packet_vote_update to every conn in dest. If dest is NULL, then
864 sends to all established connections.
865 **************************************************************************/
866 void send_updated_vote_totals(struct conn_list *dest)
868 int num_voters;
870 if (vote_list == NULL || vote_list_size(vote_list) <= 0) {
871 return;
874 log_debug("Sending updated vote totals to conn_list %p", dest);
876 if (dest == NULL) {
877 dest = game.est_connections;
880 conn_list_do_buffer(dest);
881 vote_list_iterate(vote_list, pvote) {
882 num_voters = count_voters(pvote);
883 lsend_vote_update(dest, pvote, num_voters);
884 } vote_list_iterate_end;
885 conn_list_do_unbuffer(dest);
888 /**************************************************************************
889 Returns the connection that called this vote.
890 **************************************************************************/
891 const struct connection *vote_get_caller(const struct vote *pvote)
893 return conn_by_number(pvote->caller_id);