Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/dll/acro/acro.c
1072 views
1
#include "acro.h"
2
3
srec *scores = NULL, *gscores = NULL;
4
prec *player = NULL;
5
vrec *voter = NULL;
6
grec *game = NULL;
7
8
int Acro_Init(IrcCommandDll **intp, Function_ptr *global_table)
9
{
10
initialize_module("Acromania");
11
add_module_proc(RAW_PROC, "acro", "PRIVMSG", NULL, 0, 0, acro_main, NULL);
12
add_module_proc(COMMAND_PROC, "scores", "scores", NULL, 0, 0, put_scores, NULL);
13
14
gscores = read_scores();
15
if (!game)
16
game = init_acro(game);
17
put_it("BitchX Acromania dll v0.9b by By-Tor loaded...");
18
return 0;
19
}
20
21
static int acro_main (char *comm, char *from, char *userhost, char **args)
22
{
23
if (*args[1] && !strncasecmp(args[1], "acro ", 5) && !strcasecmp(args[0], get_server_nickname(from_server)))
24
{
25
PasteArgs(args, 1);
26
switch(game->progress) {
27
case 0:
28
send_to_server("notice %s :Sorry, no game in progress.", from);
29
break;
30
case 1:
31
if (valid_acro(game, args[1]+5))
32
player = take_acro(game, player, from, userhost, args[1]+5);
33
else
34
send_to_server("PRIVMSG %s :Invalid acronym", from);
35
break;
36
case 2:
37
voter = take_vote(game, voter, player, from, userhost, args[1]+5);
38
break;
39
}
40
return 1;
41
}
42
if (*args[0] == '#' && *args[1] && !my_stricmp(args[1], "start"))
43
{
44
if (game && game->progress)
45
{
46
send_to_server("PRIVMSG %s :Game already in progress, %s. Puzzle is: %s", from, from, game->nym);
47
return 0;
48
}
49
make_acro(game);
50
game->progress = 1;
51
send_to_server("PRIVMSG %s :Round %d", args[0], game->round);
52
send_to_server("PRIVMSG %s :The acronym for this round is %s. You have 60 seconds.", args[0], game->nym);
53
send_to_server("PRIVMSG %s :/msg %s \"acro <your answer>\"", args[0], get_server_nickname(from_server));
54
add_timer(0, "Acro", 60 * 1000, 1, (int(*)(void *))warn_acro, m_sprintf("%s", args[0]), NULL, NULL, "acro");
55
}
56
return 0;
57
}
58
59
60
BUILT_IN_DLL(put_scores)
61
{
62
srec *stmp = NULL;
63
if (scores) {
64
put_it("Start Normal scores");
65
for (stmp = scores; stmp; stmp = stmp->next)
66
put_it("Nick: %s\tScore: %lu", stmp->nick, stmp->score);
67
put_it("End scores");
68
}
69
/*
70
if (gscores) {
71
put_it("GLOBAL SCORES START HERE!");
72
for (stmp = gscores; stmp; stmp = stmp->next)
73
put_it("Nick: %s\tScore %lu", stmp->nick, stmp->score);
74
put_it("GLOBAL SCORES END HERE!");
75
}
76
*/
77
}
78
79
void warn_acro(char *chan)
80
{
81
send_to_server("PRIVMSG %s :30 seconds! Puzzle is: %s", chan, game->nym);
82
add_timer(0, "Acro", 30 * 1000, 1, (int(*)(void *))start_vote, m_sprintf("%s", chan), NULL, NULL, "acro");
83
}
84
85
void start_vote(char *chan)
86
{
87
if (game->players >= MINPLAYERS)
88
{
89
send_to_server("PRIVMSG %s :Time's up, lets vote!\r\nPRIVMSG %s :/msg %s \"acro #\" to vote", chan, chan, get_server_nickname(from_server));
90
game->progress = 2;
91
show_acros(player, chan);
92
add_timer(0, "Acro", 30 * 1000, 1, (int(*)(void *))warn_vote, m_sprintf("%s", chan), NULL, NULL, "acro");
93
}
94
else if (game->extended < EXTENSIONS)
95
{
96
send_to_server("PRIVMSG %s :Aww, too few players! Puzzle is: %s", chan, game->nym);
97
add_timer(0, "Acro", 30 * 1000, 1, (int(*)(void *))start_vote, m_sprintf("%s", chan), NULL, NULL, "acro");
98
game->extended++;
99
}
100
else
101
{
102
send_to_server("PRIVMSG %s :Not enough players, ending game...", chan);
103
free_round(&player, &voter);
104
game->players = 0;
105
game->progress = 0;
106
}
107
}
108
109
void warn_vote(char *chan)
110
{
111
send_to_server("PRIVMSG %s :30 seconds left to vote!", chan);
112
add_timer(0, "Acro", 30 * 1000, 1, (int(*)(void *))end_voting, m_sprintf("%s", chan), NULL, NULL, "acro");
113
}
114
115
void end_voting(char *chan)
116
{
117
put_it("END_VOTING");
118
send_to_server("PRIVMSG %s :Voting complete, sorting scores...", chan);
119
gscores = end_vote(voter, player, gscores);
120
scores = end_vote(voter, player, scores);
121
write_scores(gscores);
122
show_scores(game, scores, gscores, chan);
123
free_round(&player, &voter);
124
if (player)
125
{
126
put_it("Player was non-null!!");
127
player = NULL;
128
}
129
if (voter)
130
{
131
put_it("voter was non-null!!");
132
voter = NULL;
133
}
134
if (game->round < game->rounds)
135
{
136
init_acro(game);
137
send_to_server("PRIVMSG %s :Round %d", chan, game->round);
138
send_to_server("PRIVMSG %s :The acronym for this round is %s. You have 60 seconds.", chan, game->nym);
139
send_to_server("PRIVMSG %s :/msg %s \"acro <your answer>\"", chan, get_server_nickname(from_server));
140
add_timer(0, "Acro", 60 * 1000, 1, (int(*)(void *))warn_acro, m_sprintf("%s", chan), NULL, NULL, "acro");
141
}
142
else
143
{
144
game->round = 1;
145
game->progress = 0;
146
free_score(&scores);
147
new_free(&game->nym);
148
init_acro(game);
149
}
150
}
151
152
grec *init_acro(grec *gtmp)
153
{
154
if (!gtmp)
155
gtmp = (grec *)new_malloc(sizeof(grec));
156
if (gtmp->nym)
157
{
158
gtmp->progress = 1;
159
gtmp->round++;
160
gtmp->players = 0;
161
gtmp->extended = 0;
162
new_free(&gtmp->nym);
163
make_acro(gtmp);
164
}
165
else
166
{
167
gtmp->progress = 0;
168
gtmp->round = 1;
169
gtmp->rounds = ROUNDS;
170
gtmp->players = 0;
171
gtmp->extended = 0;
172
gtmp->top = TOP;
173
gtmp->maxlen = MAXLEN;
174
gtmp->nym = NULL;
175
}
176
return gtmp;
177
}
178
179
void make_acro(grec *acro)
180
{
181
int i, r;
182
char *p;
183
if (acro->nym)
184
new_free(&acro->nym);
185
r = MINLENGTH+(int)((float) (1+MAXLENGTH-MINLENGTH)*random()/(RAND_MAX+1.0));
186
p = acro->nym = (char *)new_malloc(r+1);
187
for (i = 0; i < r; i++)
188
*p++ = letters[(int)((float)(strlen(letters))*random()/(RAND_MAX+1.0))];
189
return;
190
}
191
192
int valid_acro(grec *acro, char *p)
193
{
194
int spaces = 0, len = 0, gotsp = 1;
195
if (!p)
196
return 0;
197
if (!acro)
198
return 0;
199
for (; *p; p++)
200
{
201
if (isalpha(*p))
202
{
203
len++;
204
if (gotsp && (toupper(*p) != acro->nym[spaces]))
205
return 0;
206
gotsp = 0;
207
}
208
else if (*p == 32)
209
{
210
if (!gotsp)
211
{
212
spaces++;
213
gotsp = 1;
214
}
215
}
216
else return 0;
217
}
218
if ((len > strlen(acro->nym)) && (spaces+1 == strlen(acro->nym)))
219
return 1;
220
return 0;
221
}
222
223
prec *take_acro(grec *acro, prec *players, char *nick, char *host, char *stuff)
224
{
225
prec *tmp, *last = NULL;
226
if (!players)
227
{
228
players = (prec *)new_malloc(sizeof(prec));
229
players->nick = (char *)new_malloc(strlen(nick)+1);
230
players->host = (char *)new_malloc(strlen(host)+1);
231
players->acro = (char *)new_malloc(strlen(stuff)+1);
232
strcpy(players->nick, nick);
233
strcpy(players->host, host);
234
strcpy(players->acro, stuff);
235
send_to_server("PRIVMSG %s :Answer set to \"%s\"\r\nPRIVMSG %s :You are player #%d", nick, stuff, nick, ++acro->players);
236
return players;
237
}
238
for (tmp = players; tmp; tmp = tmp->next)
239
{
240
if (tmp->host && !strcasecmp(host, tmp->host))
241
{
242
if (tmp->acro && !strcasecmp(stuff, tmp->acro))
243
{
244
send_to_server("PRIVMSG %s :Your answer is alreay \"%s\"", nick, stuff);
245
return players;
246
}
247
else if (tmp->last && !strcasecmp(stuff, tmp->last))
248
{
249
RESIZE(tmp->acro, char, strlen(stuff)+1);
250
strcpy(tmp->acro, stuff);
251
send_to_server("PRIVMSG %s :Answer changed to \"%s\"", nick, stuff);
252
new_free(&tmp->last);
253
return players;
254
}
255
else {
256
tmp->last = (char *)new_malloc(strlen(stuff)+1);
257
strcpy(tmp->last, stuff);
258
send_to_server("PRIVMSG %s :You already submitted an answer, submit once more to change.", nick);
259
return players;
260
}
261
}
262
last = tmp;
263
}
264
if (acro->players < MAXPLAYERS && last)
265
{
266
tmp = last->next = (prec *)new_malloc(sizeof(prec));
267
tmp->nick = (char *)new_malloc(strlen(nick)+1);
268
tmp->host = (char *)new_malloc(strlen(host)+1);
269
tmp->acro = (char *)new_malloc(strlen(stuff)+1);
270
strcpy(tmp->nick, nick);
271
strcpy(tmp->host, host);
272
strcpy(tmp->acro, stuff);
273
send_to_server("PRIVMSG %s :Answer set to \"%s\"\r\nPRIVMSG %s :You are player #%d", nick, stuff, nick, ++acro->players);
274
}
275
else
276
send_to_server("PRIVMSG %s :Sorry, too many players.", nick);
277
return players;
278
}
279
280
vrec *take_vote(grec *acro, vrec *voters, prec *players, char *nick, char *host, char *num)
281
{
282
vrec *tmp = NULL, *last = voters;
283
int i;
284
if (atoi(num) > acro->players || atoi(num) < 1)
285
{
286
send_to_server("PRIVMSG %s :No such answer...", nick);
287
return voters;
288
}
289
for (i = 1; i < atoi(num); i++)
290
players = players->next;
291
if (players->nick && nick && !strcasecmp(players->nick, nick))
292
{
293
send_to_server("PRIVMSG %s :You can't vote for yourself.", nick);
294
return voters;
295
}
296
if (!voters)
297
{
298
voters = (vrec *)new_malloc(sizeof(vrec));
299
voters->nick = (char *)new_malloc(strlen(nick)+1);
300
voters->host = (char *)new_malloc(strlen(host)+1);
301
voters->vote = atoi(num)-1;
302
strcpy(voters->nick, nick);
303
strcpy(voters->host, host);
304
send_to_server("PRIVMSG %s :Vote recorded...", nick);
305
return voters;
306
}
307
for (tmp = voters; tmp; tmp = tmp->next)
308
{
309
if ((tmp->nick && !strcasecmp(tmp->nick, nick)) || (tmp->host && !strcasecmp(tmp->host, host)))
310
{
311
send_to_server("PRIVMSG %s :You already voted.", nick);
312
return voters;
313
}
314
last = tmp;
315
}
316
if (last && !last->next)
317
{
318
last = last->next = (vrec *)new_malloc(sizeof(vrec));
319
last->nick = (char *)new_malloc(strlen(nick)+1+sizeof(char *));
320
last->host = (char *)new_malloc(strlen(host)+1+sizeof(char *));
321
last->vote = atoi(num)-1;
322
strcpy(last->nick, nick);
323
strcpy(last->host, host);
324
send_to_server("PRIVMSG %s :Vote recorded...", nick);
325
}
326
return voters;
327
}
328
329
srec *read_scores()
330
{
331
srec *tmp, *tmp2;
332
char buff[100], *p;
333
FILE *sf;
334
tmp = tmp2 = (srec *)new_malloc(sizeof(srec));
335
memset(buff, 0, sizeof(buff));
336
sf = fopen(SCOREFILE, "r");
337
if (!sf)
338
return 0;
339
while (!feof(sf))
340
{
341
if (fgets(buff, 51, sf))
342
{
343
if (tmp->nick)
344
tmp = tmp->next = (srec *)new_malloc(sizeof(srec));
345
if (buff[strlen(buff)-1] == '\n')
346
buff[strlen(buff)-1] = 0;
347
if (!*buff)
348
break;
349
if ((p = (char *)strchr(buff, ',')))
350
*p++ = 0;
351
else if (!p)
352
{
353
return tmp2;
354
fclose(sf);
355
}
356
tmp->nick = (char *)new_malloc(strlen(buff+1));
357
strcpy(tmp->nick, buff);
358
if (p)
359
tmp->score = strtoul(p, NULL, 10);
360
}
361
else
362
break;
363
}
364
fclose(sf);
365
return tmp2;
366
}
367
368
int write_scores(srec *tmp)
369
{
370
FILE *sf;
371
if (!tmp)
372
return 0;
373
tmp = sort_scores(tmp);
374
sf = fopen(SCOREFILE, "w");
375
if (!sf)
376
return 0;
377
for (; tmp; tmp = tmp->next)
378
if (tmp->score > 0)
379
fprintf(sf, "%s,%lu\n", tmp->nick, tmp->score);
380
fclose(sf);
381
return 1;
382
}
383
384
/*
385
* Here we take the votes from the current round and translate them into
386
* scores for the players. gscores is the score per game, while scores
387
* is the overall score for all games... So we call it with a ptr to the
388
* score record we want to update and it makes it more useful :)
389
* The dual for () loop is probably inefficient, but its all I can think of
390
* right now ;), besides we aren't talking about 10,000 members here
391
392
* Eventually I'll convert this to support variable arg lengths and thus
393
* update for multiple scores with one call...
394
* This function is a mess right now, I'll clean it up later.
395
*/
396
397
srec *end_vote(vrec *voters, prec *players, srec *stmp)
398
{
399
int i, gotscore;
400
vrec *tmp = NULL;
401
prec *tmp2 = NULL;
402
srec *tmp3 = NULL, *last;
403
if (!stmp && voters && players)
404
stmp = (srec *)new_malloc(sizeof(srec));
405
for (tmp = voters; tmp; tmp = tmp->next)
406
{
407
gotscore = 0;
408
tmp2 = players;
409
for (i = 0; i < tmp->vote; i++)
410
tmp2 = tmp2->next;
411
if (stmp && !stmp->nick)
412
{
413
stmp->nick = (char *)new_malloc(strlen(tmp2->nick)+1);
414
strcpy(stmp->nick, tmp2->nick);
415
stmp->score = 1;
416
continue;
417
}
418
for (tmp3 = last = stmp; tmp3; tmp3 = tmp3->next)
419
{
420
if (tmp2->nick && tmp3->nick && !strcasecmp(tmp2->nick, tmp3->nick))
421
{
422
tmp3->score++;
423
gotscore = 1;
424
break;
425
}
426
last = tmp3;
427
}
428
if (!gotscore)
429
{
430
tmp3 = last->next = (srec *)new_malloc(sizeof(srec));
431
tmp3->nick = (char *)new_malloc(strlen(tmp2->nick)+1);
432
strcpy(tmp3->nick, tmp2->nick);
433
tmp3->score = 1;
434
}
435
}
436
return stmp;
437
}
438
439
srec *sort_scores(srec *stmp)
440
{
441
int i = 0;
442
srec *tmp;
443
srec **sort, **ctmp;
444
if (!stmp->next)
445
return stmp;
446
for (tmp = stmp; tmp; tmp = tmp->next)
447
i++;
448
ctmp = sort = (srec **)new_malloc(i*sizeof(srec *));
449
put_it("START SORTING");
450
put_scores(NULL, NULL, NULL, NULL, NULL);
451
for (tmp = stmp; tmp; tmp = tmp->next)
452
*ctmp++ = tmp;
453
qsort((void *)sort, i+1, sizeof(srec *), (int (*)(const void *, const void *))comp_score);
454
ctmp = sort;
455
for (tmp = *ctmp++; *ctmp; ctmp++)
456
tmp = tmp->next = *ctmp;
457
tmp->next = NULL;
458
tmp = *sort;
459
new_free(&sort);
460
put_scores(NULL, NULL, NULL, NULL, NULL);
461
put_it("END SCORES");
462
return tmp;
463
}
464
465
/*
466
* Here we sort deeze babys ... The return values are "opposite" so we can
467
* sort in descending order instead of ascending... Stupid declarations had
468
* me going for a while, no wonder it didnt sort right at first! :)
469
*/
470
471
int comp_score(srec **one, srec **two)
472
{
473
if ((*one)->score > (*two)->score)
474
return -1;
475
if ((*one)->score < (*two)->score)
476
return 1;
477
else
478
return strcasecmp((*one)->nick, (*two)->nick);
479
}
480
481
void show_acros(prec *players, char *chan)
482
{
483
prec *tmp;
484
int i = 1;
485
char *line, buff[201];
486
if (!players)
487
return;
488
line = (char *)new_malloc(513);
489
memset(buff, 0, sizeof(buff));
490
for (tmp = players; tmp; tmp = tmp->next)
491
{
492
snprintf(buff, 198, "PRIVMSG %s :%2d: %s", chan, i++, tmp->acro);
493
strcat(buff, "\r\n");
494
if (strlen(line)+strlen(buff) >= 512)
495
{
496
send_to_server("%s", line);
497
memset(line, 0, 513);
498
}
499
strcat(line, buff);
500
memset(buff, 0, sizeof(buff));
501
}
502
if (line)
503
send_to_server("%s", line);
504
new_free(&line);
505
}
506
507
void show_scores(grec *acro, srec *score, srec *gscore, char *chan)
508
{
509
char *line, buff[201];
510
int i;
511
line = (char *)new_malloc(513);
512
memset(buff, 0, sizeof(buff));
513
if (score)
514
score = sort_scores(score);
515
if (gscore && (acro->round >= acro->rounds))
516
gscore = sort_scores(gscore);
517
if (acro->round < acro->rounds)
518
sprintf(line, "PRIVMSG %s :Scores for round %d\r\nPRIVMSG %s :Nick Score\r\nPRIVMSG %s :-----------------\r\n", chan, acro->round, chan, chan);
519
else
520
sprintf(line, "PRIVMSG %s :Game over, tallying final scores...\r\nPRIVMSG %s : Game Score Overall Score\r\nPRIVMSG %s :Nick Score Nick Score\r\nPRIVMSG %s :----------------- -----------------\r\n", chan, chan, chan, chan);
521
for (i = 0; i < acro->top && (score || gscore); i++)
522
{
523
if ((acro->round < acro->rounds) && score)
524
{
525
snprintf(buff, 198, "PRIVMSG %s :%-9s %lu", chan, score->nick, score->score);
526
strcat(buff, "\r\n");
527
score = score->next;
528
}
529
else if (acro->round == acro->rounds && (score || gscore))
530
{
531
if (!score && gscore)
532
{
533
snprintf(buff, 198, "PRIVMSG %s : %-9s %lu", chan, gscore->nick, gscore->score);
534
strcat(buff, "\r\n");
535
gscore = gscore->next;
536
}
537
else if (score && !gscore)
538
{
539
snprintf(buff, 198, "PRIVMSG %s :%-9s %lu", chan, score->nick, score->score);
540
strcat(buff, "\r\n");
541
score = score->next;
542
}
543
else if (gscore && score)
544
{
545
snprintf(buff, 198, "PRIVMSG %s :%-9s %-5lu %-9s %lu", chan, score->nick, score->score, gscore->nick, gscore->score);
546
strcat(buff, "\r\n");
547
gscore = gscore->next;
548
score = score->next;
549
}
550
}
551
if (strlen(line)+strlen(buff) >= 512)
552
{
553
send_to_server("%s", line);
554
memset(line, 0, 513);
555
}
556
strcat(line, buff);
557
memset(buff, 0, sizeof(buff));
558
}
559
if (line)
560
send_to_server("%s", line);
561
new_free(&line);
562
}
563
564
void free_round(prec **players, vrec **voters)
565
{
566
prec *ptmp, *ptmp2;
567
vrec *vtmp, *vtmp2;
568
if (players && *players) {
569
for (ptmp = *players; ptmp;)
570
{
571
if (ptmp->nick)
572
new_free(&ptmp->nick);
573
if (ptmp->host)
574
new_free(&ptmp->host);
575
if (ptmp->acro)
576
new_free(&ptmp->acro);
577
if (ptmp->last)
578
new_free(&ptmp->last);
579
if (ptmp->next)
580
ptmp2 = ptmp->next;
581
else
582
ptmp2 = NULL;
583
new_free(&ptmp);
584
ptmp = ptmp2;
585
}
586
*players = NULL;
587
}
588
if (voters && *voters) {
589
for (vtmp = *voters; vtmp;)
590
{
591
if (vtmp->nick)
592
new_free(&vtmp->nick);
593
if (vtmp->host)
594
new_free(&vtmp->host);
595
if (vtmp->next)
596
vtmp2 = vtmp->next;
597
else
598
vtmp2 = NULL;
599
new_free(&vtmp);
600
vtmp = vtmp2;
601
}
602
*voters = NULL;
603
}
604
}
605
606
void free_score(srec **score)
607
{
608
srec *stmp, *stmp2;
609
for (stmp = *score; stmp;)
610
{
611
if (stmp->nick)
612
new_free(&stmp->nick);
613
if (stmp->next)
614
stmp2 = stmp->next;
615
else
616
stmp2 = NULL;
617
new_free(&stmp);
618
stmp = stmp2;
619
}
620
*score = NULL;
621
}
622
623