ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/modules/gameserv/dice.C
Revision: 1.7
Committed: Sat Sep 22 14:27:27 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +4 -4 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

# Content
1 /**
2 * dice.C: Dice generator.
3 *
4 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5 * Rights to this code are as documented in COPYING.
6 *
7 *
8 * Portions of this file were derived from sources bearing the following license:
9 * Copyright © 2005-2007 William Pitcock <nenolod@nenolod.net>
10 * Copyright © 2006-2007 Jilles Tjoelker <jilles@stack.nl>
11 *
12 * Rights to this code are documented in doc/pod/license.pod.
13 *
14 * $Id: dice.C,v 1.6 2007-09-16 18:54:43 pippijn Exp $
15 */
16
17 #include "atheme.h"
18 #include <ermyth/module.h>
19 #include <util/random.h>
20
21 static char const rcsid[] = "$Id: dice.C,v 1.6 2007-09-16 18:54:43 pippijn Exp $";
22
23 REGISTER_MODULE ("gameserv/dice", false, "The Ermyth Team <http://ermyth.xinutec.org>");
24
25 static void command_dice (sourceinfo_t *si, int parc, char *parv[]);
26 static void command_wod (sourceinfo_t *si, int parc, char *parv[]);
27 static void command_df (sourceinfo_t *si, int parc, char *parv[]);
28
29 command_t const cmd_dice = { "ROLL", N_("Rolls one or more dice."), AC_NONE, 2, command_dice };
30 command_t const cmd_wod = { "WOD", N_("WOD-style dice generation."), AC_NONE, 7, command_wod };
31 command_t const cmd_df = { "DF", N_("Fudge-style dice generation."), AC_NONE, 2, command_df };
32
33 E cmdvec gs_cmdtree;
34 E cmdvec cs_cmdtree;
35
36 E helpvec gs_helptree;
37 E helpvec cs_helptree;
38
39 bool
40 _modinit (module *m)
41 {
42
43 gs_cmdtree << cmd_dice;
44 gs_cmdtree << cmd_wod;
45 gs_cmdtree << cmd_df;
46
47 cs_cmdtree << cmd_dice;
48 cs_cmdtree << cmd_wod;
49 cs_cmdtree << cmd_df;
50
51 help_addentry (gs_helptree, "ROLL", "help/gameserv/roll", NULL);
52 help_addentry (cs_helptree, "ROLL", "help/gameserv/roll", NULL);
53
54 return true;
55 }
56
57 void
58 _moddeinit ()
59 {
60 gs_cmdtree >> cmd_dice;
61 gs_cmdtree >> cmd_wod;
62 gs_cmdtree >> cmd_df;
63
64 cs_cmdtree >> cmd_dice;
65 cs_cmdtree >> cmd_wod;
66 cs_cmdtree >> cmd_df;
67
68 help_delentry (gs_helptree, "ROLL");
69 help_delentry (cs_helptree, "ROLL");
70 }
71
72 /*
73 * Handle reporting for both fantasy commands and normal commands in GameServ
74 * quickly and easily. Of course, sourceinfo has a vtable that can be manipulated,
75 * but this is quicker and easier... -- nenolod
76 */
77 static void
78 gs_command_report (sourceinfo_t *si, char const * const fmt, ...)
79 {
80 va_list args;
81 char buf[BUFSIZE];
82
83 va_start (args, fmt);
84 vsnprintf (buf, BUFSIZE, fmt, args);
85 va_end (args);
86
87 if (si->c != NULL)
88 phandler->privmsg (chansvs.nick, si->c->name, "%s", buf);
89 else
90 command_success_nodata (si, "%s", buf);
91 }
92
93 static void
94 command_dice (sourceinfo_t *si, int parc, char *parv[])
95 {
96 char *arg = si->c != NULL ? parv[1] : parv[0];
97 int dice = 0, sides = 0, i = 0, roll = 0, modifier = 0;
98 char buf[BUFSIZE];
99
100 if (!arg)
101 return;
102 sscanf (arg, "%dd%d+%d", &dice, &sides, &modifier);
103
104 if (dice <= 0)
105 {
106 modifier = 0;
107 sscanf (arg, "%dd%d", &dice, &sides);
108
109 if (dice <= 0)
110 {
111 dice = 1;
112
113 sscanf (arg, "d%d+%d", &sides, &modifier);
114
115 if (sides <= 0)
116 sscanf (arg, "d%d", &sides);
117 }
118 }
119
120 if (dice > 100)
121 dice = 100;
122 if (sides > 100)
123 sides = 100;
124
125 if (dice <= 0 || sides <= 0)
126 {
127 dice = 1;
128 sides = 1;
129 }
130
131 *buf = '\0';
132
133 for (i = 0; i < dice; i++)
134 {
135 unsigned int y = 1 + gen_rand32 () % sides;
136 char buf2[BUFSIZE];
137
138 if (*buf != '\0')
139 {
140 snprintf (buf2, BUFSIZE, ", %d", y);
141 strlcat (buf, buf2, BUFSIZE);
142 }
143 else
144 {
145 snprintf (buf2, BUFSIZE, "%d", y);
146 strlcpy (buf, buf2, BUFSIZE);
147 }
148
149 roll += y;
150 }
151
152 if (modifier != 0)
153 gs_command_report (si, "(%s) + %d == \2%d\2", buf, modifier, (roll + modifier));
154 else
155 gs_command_report (si, "%s == \2%d\2", buf, roll);
156 }
157
158 static void
159 command_wod (sourceinfo_t *si, int parc, char *parv[])
160 {
161 int ii = si->c != NULL ? 1 : 0;
162 char *arg_dice = parv[ii++];
163 char *arg_difficulty = parv[ii++];
164
165 int dice, difficulty;
166 int roll, total = 0, roll_count = 0, i;
167 int success = 0, failure = 0, botches = 0, rerolls = 0;
168
169 static char buf[BUFSIZE];
170 char *end_p;
171
172 if (arg_dice == NULL || arg_difficulty == NULL)
173 {
174 command_fail (si, fault::needmoreparams, _("Syntax: WOD <dice> <difficulty>"));
175 return;
176 }
177
178 while (roll_count < 3 && arg_dice != NULL && arg_difficulty != NULL)
179 {
180 total = 0, success = 0, failure = 0, botches = 0, rerolls = 0;
181 roll_count++;
182
183 dice = atoi (arg_dice);
184 difficulty = atoi (arg_difficulty);
185
186 if (dice > 30 || dice < 1)
187 {
188 command_fail (si, fault::badparams, _("Only 1-30 dice may be thrown at one time."));
189 return;
190 }
191 else if (difficulty > 10 || difficulty < 1)
192 {
193 command_fail (si, fault::badparams, _("Difficulty setting must be between 1 and 10."));
194 return;
195 }
196 else
197 {
198 end_p = buf;
199
200 for (i = 0; i < dice; i++)
201 {
202 roll = (gen_rand32 () % 10) + 1;
203
204 end_p += snprintf (end_p, BUFSIZE - (end_p - buf), "%d ", roll);
205
206 if (roll == 1)
207 {
208 botches++;
209 continue;
210 }
211 else if (roll == 10)
212 rerolls++;
213
214 if (roll >= difficulty)
215 success++;
216 else
217 failure++;
218 }
219
220 rerolls = rerolls - botches;
221 total = success - botches;
222
223 gs_command_report (si, _("%s rolls %d dice at difficulty %d: %s"), si->su->nick, dice, difficulty, buf);
224
225 if (rerolls > 0)
226 gs_command_report (si, _("Successes: %d, Failures: %d, Botches: %d, Total: %d. You may reroll %d if you have a specialty."), success, failure, botches, total, rerolls);
227 else
228 gs_command_report (si, _("Successes: %d, Failures: %d, Botches: %d, Total: %d."), success, failure, botches, total);
229 }
230
231 /* prepare for another go. */
232 arg_dice = parv[ii++];
233 arg_difficulty = parv[ii++];
234 }
235 }
236
237 static char const * const df_dice_table[] = { "[-]", "[ ]", "[+]" };
238
239 static void
240 command_df (sourceinfo_t *si, int parc, char *parv[])
241 {
242 int ii = si->c != NULL ? 1 : 0;
243 char *arg_dice = parv[ii++];
244 char buf[BUFSIZE];
245 int i, dice;
246
247 if (arg_dice == NULL)
248 {
249 command_fail (si, fault::needmoreparams, _("Syntax: DF <dice>"));
250 return;
251 }
252
253 dice = atoi (arg_dice);
254 *buf = '\0';
255
256 if (dice > 30 || dice < 1)
257 {
258 command_fail (si, fault::badparams, _("Only 1-30 dice may be thrown at one time."));
259 return;
260 }
261
262 for (i = 0; i < dice; i++)
263 {
264 int roll = gen_rand32 () % 3;
265
266 if (*buf != '\0')
267 strlcat (buf, df_dice_table[roll], BUFSIZE);
268 else
269 strlcpy (buf, df_dice_table[roll], BUFSIZE);
270 }
271
272 gs_command_report (si, _("Result: %s"), buf);
273 }