Freeciv-3.2: /fast/freeciv/nightly/S3_2/server/voting.c Source File

Freeciv-3.2

Loading...
Searching...
No Matches
voting.c
Go to the documentation of this file.
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.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <math.h>
19
20/* utility */
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "capability.h"
27#include "connection.h"
28#include "packets.h"
29#include "player.h"
30
31/* server */
32#include "commands.h"
33#include "console.h"
34#include <hand_gen.h> /* <> so looked from the build directory first. */
35#include "notify.h"
36#include "settings.h"
37#include "stdinhand.h"
38
39#include "voting.h"
40
41 struct vote_list *vote_list = NULL;
42 int vote_number_sequence = 0;
43
44
45/**********************************************************************/
48 int count_voters(const struct vote *pvote)
49{
50 int num_voters = 0;
51
52 conn_list_iterate(game.est_connections, pconn) {
53 if (conn_can_vote(pconn, pvote)) {
54 num_voters++;
55 }
56 } conn_list_iterate_end;
57
58 return num_voters;
59}
60
61/**********************************************************************/
64 static void lsend_vote_new(struct conn_list *dest, struct vote *pvote)
65{
66 struct packet_vote_new packet;
67 struct connection *pconn;
68
69 if (pvote == NULL) {
70 return;
71 }
72
73 pconn = conn_by_number(pvote->caller_id);
74 if (pconn == NULL) {
75 return;
76 }
77
78 log_debug("lsend_vote_new %p (%d) --> %p", pvote, pvote->vote_no, dest);
79
80 packet.vote_no = pvote->vote_no;
81 sz_strlcpy(packet.user, pconn->username);
82 describe_vote(pvote, packet.desc, sizeof(packet.desc));
83
84 packet.percent_required = 100 * pvote->need_pc;
85 packet.flags = pvote->flags;
86
87 if (dest == NULL) {
88 dest = game.est_connections;
89 }
90
91 conn_list_iterate(dest, conn) {
92 if (!conn_can_see_vote(conn, pvote)) {
93 continue;
94 }
95 send_packet_vote_new(conn, &packet);
96 } conn_list_iterate_end;
97}
98
99/**********************************************************************/
102 static void lsend_vote_update(struct conn_list *dest, struct vote *pvote,
103 int num_voters)
104{
105 struct packet_vote_update packet;
106 struct connection *pconn;
107
108 if (pvote == NULL) {
109 return;
110 }
111
112 pconn = conn_by_number(pvote->caller_id);
113 if (pconn == NULL) {
114 return;
115 }
116
117 log_debug("lsend_vote_update %p (%d) --> %p", pvote, pvote->vote_no, dest);
118
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;
124
125 if (dest == NULL) {
126 dest = game.est_connections;
127 }
128
129 conn_list_iterate(dest, aconn) {
130 if (!conn_can_see_vote(aconn, pvote)) {
131 continue;
132 }
133 send_packet_vote_update(aconn, &packet);
134 } conn_list_iterate_end;
135}
136
137/**********************************************************************/
140 static void lsend_vote_remove(struct conn_list *dest, struct vote *pvote)
141{
142 struct packet_vote_remove packet;
143
144 if (!pvote) {
145 return;
146 }
147
148 packet.vote_no = pvote->vote_no;
149
150 if (dest == NULL) {
151 dest = game.est_connections;
152 }
153
154 conn_list_iterate(dest, pconn) {
155 send_packet_vote_remove(pconn, &packet);
156 } conn_list_iterate_end;
157}
158
159/**********************************************************************/
162 static void lsend_vote_resolve(struct conn_list *dest,
163 struct vote *pvote, bool passed)
164{
165 struct packet_vote_resolve packet;
166
167 if (!pvote) {
168 return;
169 }
170
171 packet.vote_no = pvote->vote_no;
172 packet.passed = passed;
173
174 if (dest == NULL) {
175 dest = game.est_connections;
176 }
177
178 conn_list_iterate(dest, pconn) {
179 if (!conn_can_see_vote(pconn, pvote)) {
180 continue;
181 }
182 send_packet_vote_resolve(pconn, &packet);
183 } conn_list_iterate_end;
184}
185
186/**********************************************************************/
189 static void free_vote(struct vote *pvote)
190{
191 if (!pvote) {
192 return;
193 }
194
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);
200}
201
202/**********************************************************************/
205 void remove_vote(struct vote *pvote)
206{
207 if (!vote_list || !pvote) {
208 return;
209 }
210
211 vote_list_remove(vote_list, pvote);
212 lsend_vote_remove(NULL, pvote);
213 free_vote(pvote);
214}
215
216/**********************************************************************/
219 void clear_all_votes(void)
220{
221 if (!vote_list) {
222 return;
223 }
224
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);
230}
231
232/**********************************************************************/
235 bool vote_is_team_only(const struct vote *pvote)
236{
237 return pvote && (pvote->flags & VCF_TEAMONLY);
238}
239
240/**********************************************************************/
248 bool conn_can_vote(const struct connection *pconn, const struct vote *pvote)
249{
250 if (!pconn || !conn_controls_player(pconn)
251 || conn_get_access(pconn) < ALLOW_BASIC) {
252 return FALSE;
253 }
254
255 if (vote_is_team_only(pvote)) {
256 const struct player *pplayer, *caller_plr;
257
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;
263 }
264 }
265
266 return TRUE;
267}
268
269/**********************************************************************/
272 bool conn_can_see_vote(const struct connection *pconn,
273 const struct vote *pvote)
274{
275 if (!pconn) {
276 return FALSE;
277 }
278
279 if (conn_is_global_observer(pconn)) {
280 /* All is visible for global observer. */
281 return TRUE;
282 }
283
284 if (vote_is_team_only(pvote)) {
285 const struct player *pplayer, *caller_plr;
286
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;
292 }
293 }
294
295 return TRUE;
296}
297
298/**********************************************************************/
301 struct vote *get_vote_by_no(int vote_no)
302{
303 if (!vote_list) {
304 return NULL;
305 }
306
307 vote_list_iterate(vote_list, pvote) {
308 if (pvote->vote_no == vote_no) {
309 return pvote;
310 }
311 } vote_list_iterate_end;
312
313 return NULL;
314}
315
316/**********************************************************************/
319 struct vote *get_vote_by_caller(const struct connection *caller)
320{
321 if (caller == NULL || !vote_list) {
322 return NULL;
323 }
324
325 vote_list_iterate(vote_list, pvote) {
326 if (pvote->caller_id == caller->id) {
327 return pvote;
328 }
329 } vote_list_iterate_end;
330
331 return NULL;
332}
333
334/**********************************************************************/
338 struct vote *vote_new(struct connection *caller,
339 const char *allargs,
340 int command_id)
341{
342 struct vote *pvote;
343 const struct command *pcmd;
344
345 if (!conn_can_vote(caller, NULL)) {
346 return NULL;
347 }
348
349 /* Cancel previous vote */
350 remove_vote(get_vote_by_caller(caller));
351
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);
357
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);
362 }
363
364 pvote->turn_count = 0;
365 pvote->votes_cast = vote_cast_list_new();
366 pvote->vote_no = ++vote_number_sequence;
367
368 vote_list_append(vote_list, pvote);
369
370 pvote->flags = command_vote_flags(pcmd);
371 pvote->need_pc = (double) command_vote_percent(pcmd) / 100.0;
372
373 if (pvote->flags & VCF_NOPASSALONE) {
374 int num_voters = count_voters(pvote);
375 double min_pc = 1.0 / (double) num_voters;
376
377 if (num_voters > 1 && min_pc > pvote->need_pc) {
378 pvote->need_pc = MIN(0.5, 2.0 * min_pc);
379 }
380 }
381
382 lsend_vote_new(NULL, pvote);
383
384 return pvote;
385}
386
387/**********************************************************************/
391 bool vote_would_pass_immediately(const struct connection *caller,
392 int command_id)
393{
394 struct vote virtual_vote;
395 const struct command *pcmd;
396
397 if (!conn_can_vote(caller, NULL)) {
398 return FALSE;
399 }
400
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);
405
406 if (virtual_vote.flags & VCF_NOPASSALONE) {
407 return FALSE;
408 }
409
410 virtual_vote.caller_id = caller->id;
411 return (((double) (command_vote_percent(pcmd)
412 * count_voters(&virtual_vote)) / 100.0) < 1.0);
413}
414
415/**********************************************************************/
420 static void check_vote(struct vote *pvote)
421{
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;
432
433 if (!pvote) {
434 return;
435 }
436
437 pvote->yes = 0;
438 pvote->no = 0;
439 pvote->abstain = 0;
440
441 num_voters = count_voters(pvote);
442
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;
447 }
448 num_cast++;
449
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;
462 }
463
464 log_error("Unknown vote cast variant: %d.", pvc->vote_cast);
465 pvote->abstain++;
466 } vote_cast_list_iterate_end;
467
468 flags = pvote->flags;
469 need_pc = pvote->need_pc;
470
471 /* Check if we should resolve the vote. */
472 if (num_voters > 0) {
473
474 /* Players that abstain essentially remove themselves from
475 * the voting pool. */
476 base = num_voters - pvote->abstain;
477
478 if (base > MY_EPSILON) {
479 yes_pc = (double) pvote->yes / base;
480 no_pc = (double) pvote->no / base;
481
482 /* The fraction of people who have not voted at all. */
483 rem_pc = (double) (num_voters - num_cast) / base;
484 }
485
486 if (flags & VCF_NODISSENT && no_pc > MY_EPSILON) {
487 resolve = TRUE;
488 }
489
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));
501 }
502
503 /* Resolve if everyone voted already. */
504 if (!resolve && fabs(rem_pc) < MY_EPSILON) {
505 resolve = TRUE;
506 }
507
508 /* Resolve this vote if it has been around long enough. */
509 if (!resolve && pvote->turn_count > 1) {
510 resolve = TRUE;
511 }
512
513 /* Resolve this vote if everyone tries to abstain. */
514 if (!resolve && fabs(base) < MY_EPSILON) {
515 resolve = TRUE;
516 }
517 }
518
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);
522
523 lsend_vote_update(NULL, pvote, num_voters);
524
525 if (!resolve) {
526 return;
527 }
528
529 passed = yes_pc - need_pc > MY_EPSILON;
530
531 if (passed && flags & VCF_NODISSENT) {
532 passed = fabs(no_pc) < MY_EPSILON;
533 }
534
535 if (vote_is_team_only(pvote)) {
536 const struct connection *caller;
537
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;
546 }
547
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);
562 }
563
564 lsend_vote_resolve(NULL, pvote, passed);
565
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;
573 }
574
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;
593 }
594 } vote_cast_list_iterate_end;
595
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);
602
603 if (passed) {
604 handle_stdin_input(NULL, cmdline);
605 }
606}
607
608/**********************************************************************/
611 static struct vote_cast *vote_cast_find(struct vote *pvote, int conn_id)
612{
613 if (!pvote) {
614 return NULL;
615 }
616
617 vote_cast_list_iterate(pvote->votes_cast, pvc) {
618 if (pvc->conn_id == conn_id) {
619 return pvc;
620 }
621 } vote_cast_list_iterate_end;
622
623 return NULL;
624}
625
626/**********************************************************************/
629 static struct vote_cast *vote_cast_new(struct vote *pvote)
630{
631 struct vote_cast *pvc;
632
633 if (!pvote) {
634 return NULL;
635 }
636
637 pvc = fc_malloc(sizeof(struct vote_cast));
638 pvc->conn_id = -1;
639 pvc->vote_cast = VOTE_ABSTAIN;
640
641 vote_cast_list_append(pvote->votes_cast, pvc);
642
643 return pvc;
644}
645
646/**********************************************************************/
649 static void remove_vote_cast(struct vote *pvote, struct vote_cast *pvc)
650{
651 if (!pvote || !pvc) {
652 return;
653 }
654
655 vote_cast_list_remove(pvote->votes_cast, pvc);
656 free(pvc);
657 check_vote(pvote); /* Maybe can pass */
658}
659
660/**********************************************************************/
663 void connection_vote(struct connection *pconn,
664 struct vote *pvote,
665 enum vote_type type)
666{
667 struct vote_cast *pvc;
668
669 if (!conn_can_vote(pconn, pvote)) {
670 return;
671 }
672
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;
684 }
685 check_vote(pvote);
686}
687
688/**********************************************************************/
691 void cancel_connection_votes(struct connection *pconn)
692{
693 if (!pconn || !vote_list) {
694 return;
695 }
696
697 remove_vote(get_vote_by_caller(pconn));
698
699 vote_list_iterate(vote_list, pvote) {
700 remove_vote_cast(pvote, vote_cast_find(pvote, pconn->id));
701 } vote_list_iterate_end;
702}
703
704/**********************************************************************/
707 void voting_init(void)
708{
709 if (!vote_list) {
710 vote_list = vote_list_new();
711 vote_number_sequence = 0;
712 }
713}
714
715/**********************************************************************/
718 void voting_turn(void)
719{
720 if (!vote_list) {
721 log_error("voting_turn() called before voting_init()");
722 return;
723 }
724
725 vote_list_iterate(vote_list, pvote) {
726 pvote->turn_count++;
727 check_vote(pvote);
728 } vote_list_iterate_end;
729}
730
731/**********************************************************************/
734 void voting_free(void)
735{
736 clear_all_votes();
737 if (vote_list) {
738 vote_list_destroy(vote_list);
739 vote_list = NULL;
740 }
741}
742
743/**********************************************************************/
748 int describe_vote(struct vote *pvote, char *buf, int buflen)
749{
750 int ret = 0;
751
752 /* NB We don't handle votes with multiple flags here. */
753
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));
766 }
767
768 return ret;
769}
770
771/**********************************************************************/
775 void handle_vote_submit(struct connection *pconn, int vote_no, int value)
776{
777 struct vote *pvote;
778 enum vote_type type;
779
780 log_debug("Got vote submit (%d %d) from %s.",
781 vote_no, value, conn_description(pconn));
782
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;
790 }
791
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;
802 }
803
804 connection_vote(pconn, pvote, type);
805}
806
807/**********************************************************************/
810 void send_running_votes(struct connection *pconn, bool only_team_votes)
811{
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;
817 }
818
819 log_debug("Sending %s running votes to %s.",
820 only_team_votes ? "team" : "all", conn_description(pconn));
821
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));
828 }
829 } else if (!only_team_votes) {
830 lsend_vote_new(pconn->self, pvote);
831 lsend_vote_update(pconn->self, pvote, count_voters(pvote));
832 }
833 } vote_list_iterate_end;
834 connection_do_unbuffer(pconn);
835}
836
837/**********************************************************************/
841 void send_remove_team_votes(struct connection *pconn)
842{
843 if (NULL == vote_list
844 || vote_list_size(vote_list) < 1
845 || NULL == pconn
846 || NULL == conn_get_player(pconn)) {
847 return;
848 }
849
850 log_debug("Sending remove info of the team votes to %s.",
851 conn_description(pconn));
852
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);
857 }
858 } vote_list_iterate_end;
859 connection_do_unbuffer(pconn);
860}
861
862/**********************************************************************/
866 void send_updated_vote_totals(struct conn_list *dest)
867{
868 int num_voters;
869
870 if (vote_list == NULL || vote_list_size(vote_list) <= 0) {
871 return;
872 }
873
874 log_debug("Sending updated vote totals to conn_list %p", dest);
875
876 if (dest == NULL) {
877 dest = game.est_connections;
878 }
879
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);
886}
887
888/**********************************************************************/
891 const struct connection *vote_get_caller(const struct vote *pvote)
892{
893 return conn_by_number(pvote->caller_id);
894}
capability.h
command_name
const char * command_name(const struct command *pcommand)
Definition commands.c:743
command_vote_percent
int command_vote_percent(const struct command *pcommand)
Definition commands.c:815
command_by_number
const struct command * command_by_number(int i)
Definition commands.c:734
command_vote_flags
int command_vote_flags(const struct command *pcommand)
Definition commands.c:807
commands.h
command_id
command_id
Definition commands.h:35
incite_cost
char * incite_cost
Definition comments.c:74
conn_get_player
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:763
conn_list_do_unbuffer
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:366
conn_list_do_buffer
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:356
connection_do_buffer
void connection_do_buffer(struct connection *pc)
Definition connection.c:324
conn_controls_player
bool conn_controls_player(const struct connection *pconn)
Definition connection.c:745
conn_is_global_observer
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:753
conn_description
const char * conn_description(const struct connection *pconn)
Definition connection.c:474
conn_by_number
struct connection * conn_by_number(int id)
Definition connection.c:421
conn_get_access
enum cmdlevel conn_get_access(const struct connection *pconn)
Definition connection.c:775
connection_do_unbuffer
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:336
connection.h
conn_list_iterate
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
conn_list_iterate_end
#define conn_list_iterate_end
Definition connection.h:110
console.h
MAX_LEN_CONSOLE_LINE
#define MAX_LEN_CONSOLE_LINE
Definition console.h:19
base
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2931
fcintl.h
_
#define _(String)
Definition fcintl.h:67
ftc_vote_abstain
const struct ft_color ftc_vote_abstain
Definition featured_text.c:97
ftc_vote_failed
const struct ft_color ftc_vote_failed
Definition featured_text.c:94
ftc_vote_yes
const struct ft_color ftc_vote_yes
Definition featured_text.c:95
ftc_vote_no
const struct ft_color ftc_vote_no
Definition featured_text.c:96
ftc_vote_passed
const struct ft_color ftc_vote_passed
Definition featured_text.c:93
game
struct civ_game game
Definition game.c:62
title
const char * title
Definition repodlgs.c:1314
type
GType type
Definition repodlgs.c:1313
hand_gen.h
log.h
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
log_debug
#define log_debug(message,...)
Definition log.h:115
log_error
#define log_error(message,...)
Definition log.h:103
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
notify_team
void notify_team(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:346
notify.h
packets.h
send_packet_vote_resolve
int send_packet_vote_resolve(struct connection *pc, const struct packet_vote_resolve *packet)
Definition packets_gen.c:74866
send_packet_vote_remove
int send_packet_vote_remove(struct connection *pc, const struct packet_vote_remove *packet)
Definition packets_gen.c:74680
send_packet_vote_update
int send_packet_vote_update(struct connection *pc, const struct packet_vote_update *packet)
Definition packets_gen.c:74514
send_packet_vote_new
int send_packet_vote_new(struct connection *pc, const struct packet_vote_new *packet)
Definition packets_gen.c:74168
players_on_same_team
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1476
player.h
settings.h
MIN
#define MIN(x, y)
Definition shared.h:55
handle_stdin_input
bool handle_stdin_input(struct connection *caller, char *str)
Definition stdinhand.c:4426
stdinhand.h
civ_game::est_connections
struct conn_list * est_connections
Definition game.h:97
command
Definition commands.c:37
connection
Definition connection.h:136
connection::id
int id
Definition connection.h:137
packet_vote_new
Definition packets_gen.h:1628
packet_vote_new::flags
int flags
Definition packets_gen.h:1633
packet_vote_new::vote_no
int vote_no
Definition packets_gen.h:1629
packet_vote_new::desc
char desc[512]
Definition packets_gen.h:1631
packet_vote_new::percent_required
int percent_required
Definition packets_gen.h:1632
packet_vote_new::user
char user[MAX_LEN_NAME]
Definition packets_gen.h:1630
packet_vote_remove
Definition packets_gen.h:1644
packet_vote_remove::vote_no
int vote_no
Definition packets_gen.h:1645
packet_vote_resolve
Definition packets_gen.h:1648
packet_vote_resolve::passed
bool passed
Definition packets_gen.h:1650
packet_vote_resolve::vote_no
int vote_no
Definition packets_gen.h:1649
packet_vote_update
Definition packets_gen.h:1636
packet_vote_update::abstain
int abstain
Definition packets_gen.h:1640
packet_vote_update::num_voters
int num_voters
Definition packets_gen.h:1641
packet_vote_update::yes
int yes
Definition packets_gen.h:1638
packet_vote_update::no
int no
Definition packets_gen.h:1639
packet_vote_update::vote_no
int vote_no
Definition packets_gen.h:1637
player
Definition player.h:247
player::flags
bv_plr_flags flags
Definition player.h:290
vote_cast
Definition voting.h:34
vote_cast::conn_id
int conn_id
Definition voting.h:36
vote_cast::vote_cast
enum vote_type vote_cast
Definition voting.h:35
vote
Definition voting.h:46
vote::vote_no
int vote_no
Definition voting.h:52
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
support.h
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:189
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
sz_strlcat
#define sz_strlcat(dest, src)
Definition support.h:190
send_running_votes
void send_running_votes(struct connection *pconn, bool only_team_votes)
Definition voting.c:810
lsend_vote_new
static void lsend_vote_new(struct conn_list *dest, struct vote *pvote)
Definition voting.c:64
send_remove_team_votes
void send_remove_team_votes(struct connection *pconn)
Definition voting.c:841
describe_vote
int describe_vote(struct vote *pvote, char *buf, int buflen)
Definition voting.c:748
lsend_vote_remove
static void lsend_vote_remove(struct conn_list *dest, struct vote *pvote)
Definition voting.c:140
conn_can_vote
bool conn_can_vote(const struct connection *pconn, const struct vote *pvote)
Definition voting.c:248
check_vote
static void check_vote(struct vote *pvote)
Definition voting.c:420
vote_new
struct vote * vote_new(struct connection *caller, const char *allargs, int command_id)
Definition voting.c:338
vote_is_team_only
bool vote_is_team_only(const struct vote *pvote)
Definition voting.c:235
cancel_connection_votes
void cancel_connection_votes(struct connection *pconn)
Definition voting.c:691
get_vote_by_no
struct vote * get_vote_by_no(int vote_no)
Definition voting.c:301
vote_number_sequence
int vote_number_sequence
Definition voting.c:42
vote_would_pass_immediately
bool vote_would_pass_immediately(const struct connection *caller, int command_id)
Definition voting.c:391
send_updated_vote_totals
void send_updated_vote_totals(struct conn_list *dest)
Definition voting.c:866
handle_vote_submit
void handle_vote_submit(struct connection *pconn, int vote_no, int value)
Definition voting.c:775
voting_turn
void voting_turn(void)
Definition voting.c:718
lsend_vote_resolve
static void lsend_vote_resolve(struct conn_list *dest, struct vote *pvote, bool passed)
Definition voting.c:162
clear_all_votes
void clear_all_votes(void)
Definition voting.c:219
get_vote_by_caller
struct vote * get_vote_by_caller(const struct connection *caller)
Definition voting.c:319
voting_init
void voting_init(void)
Definition voting.c:707
lsend_vote_update
static void lsend_vote_update(struct conn_list *dest, struct vote *pvote, int num_voters)
Definition voting.c:102
free_vote
static void free_vote(struct vote *pvote)
Definition voting.c:189
vote_cast_find
static struct vote_cast * vote_cast_find(struct vote *pvote, int conn_id)
Definition voting.c:611
connection_vote
void connection_vote(struct connection *pconn, struct vote *pvote, enum vote_type type)
Definition voting.c:663
vote_list
struct vote_list * vote_list
Definition voting.c:41
vote_get_caller
const struct connection * vote_get_caller(const struct vote *pvote)
Definition voting.c:891
count_voters
int count_voters(const struct vote *pvote)
Definition voting.c:48
remove_vote_cast
static void remove_vote_cast(struct vote *pvote, struct vote_cast *pvc)
Definition voting.c:649
remove_vote
void remove_vote(struct vote *pvote)
Definition voting.c:205
voting_free
void voting_free(void)
Definition voting.c:734
vote_cast_new
static struct vote_cast * vote_cast_new(struct vote *pvote)
Definition voting.c:629
conn_can_see_vote
bool conn_can_see_vote(const struct connection *pconn, const struct vote *pvote)
Definition voting.c:272
voting.h
vote_type
vote_type
Definition voting.h:26
VOTE_ABSTAIN
@ VOTE_ABSTAIN
Definition voting.h:27
VOTE_YES
@ VOTE_YES
Definition voting.h:27
VOTE_NUM
@ VOTE_NUM
Definition voting.h:27
VOTE_NO
@ VOTE_NO
Definition voting.h:27
vote_list_iterate_end
#define vote_list_iterate_end
Definition voting.h:65
VCF_TEAMONLY
@ VCF_TEAMONLY
Definition voting.h:23
VCF_NOPASSALONE
@ VCF_NOPASSALONE
Definition voting.h:21
VCF_NODISSENT
@ VCF_NODISSENT
Definition voting.h:20
vote_cast_list_iterate
#define vote_cast_list_iterate(alist, pvc)
Definition voting.h:42
vote_list_iterate
#define vote_list_iterate(alist, pvote)
Definition voting.h:63
vote_cast_list_iterate_end
#define vote_cast_list_iterate_end
Definition voting.h:44