ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/gameserv/dice.C
Revision: 1.7
Committed: Sat Sep 22 14:27:27 2007 UTC (19 years 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

# User Rev Content
1 pippijn 1.6 /**
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 pippijn 1.4 * Copyright © 2005-2007 William Pitcock <nenolod@nenolod.net>
10     * Copyright © 2006-2007 Jilles Tjoelker <jilles@stack.nl>
11 pippijn 1.1 *
12 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
13 pippijn 1.1 *
14 pippijn 1.7 * $Id: dice.C,v 1.6 2007-09-16 18:54:43 pippijn Exp $
15 pippijn 1.1 */
16    
17     #include "atheme.h"
18 pippijn 1.4 #include <ermyth/module.h>
19 pippijn 1.7 #include <util/random.h>
20 pippijn 1.1
21 pippijn 1.7 static char const rcsid[] = "$Id: dice.C,v 1.6 2007-09-16 18:54:43 pippijn Exp $";
22 pippijn 1.1
23 pippijn 1.7 REGISTER_MODULE ("gameserv/dice", false, "The Ermyth Team <http://ermyth.xinutec.org>");
24 pippijn 1.1
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 pippijn 1.4 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 pippijn 1.1
33 pippijn 1.4 E cmdvec gs_cmdtree;
34     E cmdvec cs_cmdtree;
35 pippijn 1.1
36 pippijn 1.4 E helpvec gs_helptree;
37     E helpvec cs_helptree;
38 pippijn 1.1
39 pippijn 1.4 bool
40     _modinit (module *m)
41 pippijn 1.1 {
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 pippijn 1.4
54     return true;
55 pippijn 1.1 }
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 pippijn 1.4 gs_command_report (sourceinfo_t *si, char const * const fmt, ...)
79 pippijn 1.1 {
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 pippijn 1.4 phandler->privmsg (chansvs.nick, si->c->name, "%s", buf);
89 pippijn 1.1 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 pippijn 1.4 unsigned int y = 1 + gen_rand32 () % sides;
136 pippijn 1.1 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 pippijn 1.5 command_fail (si, fault::needmoreparams, _("Syntax: WOD <dice> <difficulty>"));
175 pippijn 1.1 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 pippijn 1.5 command_fail (si, fault::badparams, _("Only 1-30 dice may be thrown at one time."));
189 pippijn 1.1 return;
190     }
191     else if (difficulty > 10 || difficulty < 1)
192     {
193 pippijn 1.5 command_fail (si, fault::badparams, _("Difficulty setting must be between 1 and 10."));
194 pippijn 1.1 return;
195     }
196     else
197     {
198     end_p = buf;
199    
200     for (i = 0; i < dice; i++)
201     {
202 pippijn 1.4 roll = (gen_rand32 () % 10) + 1;
203 pippijn 1.1
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 pippijn 1.4 static char const * const df_dice_table[] = { "[-]", "[ ]", "[+]" };
238 pippijn 1.1
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 pippijn 1.5 command_fail (si, fault::needmoreparams, _("Syntax: DF <dice>"));
250 pippijn 1.1 return;
251     }
252    
253     dice = atoi (arg_dice);
254     *buf = '\0';
255    
256     if (dice > 30 || dice < 1)
257     {
258 pippijn 1.5 command_fail (si, fault::badparams, _("Only 1-30 dice may be thrown at one time."));
259 pippijn 1.1 return;
260     }
261    
262     for (i = 0; i < dice; i++)
263     {
264 pippijn 1.4 int roll = gen_rand32 () % 3;
265 pippijn 1.1
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     }