/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/ladder_calc.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bnetd/ladder_calc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (hide annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

1 sysadm 1.1 /*
2     * Copyright (C) 1999 Rob Crittenden (rcrit@greyoak.com)
3     * Copyright (C) 1999,2000 Ross Combs (rocombs@cs.nmsu.edu)
4     * Copyright (C) 1999,2000 D.Moreaux (vapula@linuxbe.org)
5     *
6     * This program is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU General Public License
8     * as published by the Free Software Foundation; either version 2
9     * of the License, or (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19     */
20     #include "common/setup_before.h"
21     #include <math.h>
22     #ifdef HAVE_STRING_H
23     # include <string.h>
24     #else
25     # ifdef HAVE_STRINGS_H
26     # include <strings.h>
27     # endif
28     #endif
29     #include "account.h"
30     #include "account_wrap.h"
31     #include "common/eventlog.h"
32     #include "game.h"
33     #include "common/tag.h"
34     #include "ladder.h"
35     #include "ladder_calc.h"
36     #include "common/xalloc.h"
37     #include "common/setup_after.h"
38    
39    
40     static double probability(unsigned int a, unsigned int b) ;
41     static int coefficient(t_account * account, t_clienttag clienttag, t_ladder_id id);
42    
43     static double two_player(unsigned int *rating);
44    
45     static double three_player(unsigned int *rating);
46    
47     static double four_player(unsigned int *rating);
48    
49     static double five_player(unsigned int *rating);
50     static double five_f1(int a, int b, int c, int d, int e) ;
51     static double five_f2(int a, int b, int c) ;
52    
53     static double six_player(unsigned int *rating);
54     static double six_f1(int a, int b, int c, int d, int e, int f) ;
55     static double six_f2(int a, int b, int c, int d, int e, int f) ;
56     static double six_f3(int a, int b, int c, int d) ;
57    
58     static double seven_player(unsigned int *rating);
59     static double seven_f1(int a, int b, int c, int d, int e, int f, int g) ;
60     static double seven_f2(int a, int b, int c, int d, int e, int f, int g) ;
61    
62     static double eight_player(unsigned int *rating);
63     static double eight_f1(int a, int b, int c, int d, int e, int f, int g) ;
64     static double eight_f2(int a, int b, int c, int d, int e, int f, int g) ;
65     static double eight_f3(int a, int b, int c, int d, int e) ;
66    
67     /*
68     * Compute probability of winning using the Elo system
69     *
70     * The formula is:
71     *
72     * D = rating(player a) - rating(player b)
73     *
74     * 1
75     * Pwin(D) = ------------------
76     * -(D / 400)
77     * 1 + 10
78     */
79     static double probability(unsigned int a, unsigned int b)
80     {
81     double i, j;
82    
83     i = (((double)a) - ((double)b)) / 400.0;
84    
85     j = pow(10.0,-i);
86    
87     return (1.0 / (1.0+j));
88     }
89    
90    
91     /*
92     * This is the coefficient k which is meant to enhance the
93     * effect of the Elo system where more experienced players
94     * will gain fewer points when playing against newbies, and
95     * newbies will gain massive points if they win against an
96     * experienced player. It also helps stabilize a player's
97     * rating after they have played 30 games or so.
98     *
99     * K=50 for new players
100     * K=30 for players who have played 30 or more ladder games
101     * K=20 for players who have attained a rating of 2400 or higher
102     */
103     static int coefficient(t_account * account, t_clienttag clienttag, t_ladder_id id)
104     {
105     int const total_ladder_games=account_get_ladder_wins(account,clienttag,id) +
106     account_get_ladder_losses(account,clienttag,id) +
107     account_get_ladder_disconnects(account,clienttag,id);
108    
109     if (total_ladder_games < 30)
110     return 50;
111    
112     if (account_get_ladder_rating(account,clienttag,id) < 2400)
113     return 30;
114    
115     return 20;
116     }
117    
118    
119     /*
120     * The Elo system only handles 2 players, these functions extend
121     * the calculation to different numbers of players as if they were
122     * in a tournament. It turns out the math for this is really ugly,
123     * so we have hardcoded the equations for every number of players.
124     */
125     static double two_player(unsigned int *rating)
126     {
127     unsigned int a,b;
128     double ab;
129    
130     a = rating[0];
131     b = rating[1];
132    
133     ab = probability(a,b);
134    
135     return ab;
136     }
137    
138     static double three_player(unsigned int *rating)
139     {
140     unsigned int a,b,c;
141     double ab,ac,bc,cb;
142    
143     a = rating[0];
144     b = rating[1];
145     c = rating[2];
146    
147     ab = probability(a,b);
148     ac = probability(a,c);
149     bc = probability(b,c);
150     cb = 1.0 - bc;
151    
152     return (2*(ab*ac)+(bc*ab)+(cb*ac))/3;
153     }
154    
155     static double four_player(unsigned int *rating)
156     {
157     unsigned int a,b,c,d;
158     double ab,ac,ad,bc,bd,cb,cd,db,dc;
159    
160     a = rating[0];
161     b = rating[1];
162     c = rating[2];
163     d = rating[3];
164    
165    
166     ab = probability(a,b);
167     ac = probability(a,c);
168     ad = probability(a,d);
169     bc = probability(b,c);
170     bd = probability(b,d);
171     cd = probability(c,d);
172     cb = 1.0 - bc;
173     db = 1.0 - bd;
174     dc = 1.0 - cd;
175    
176     return (ab*ac*(cd+bd)+ac*ad*(db+cb)+ab*ad*(dc+bc))/3;
177     }
178    
179    
180     /* [Denis MOREAUX <vapula@linuxbe.org>, 10 Apr 2000]
181     *
182     * C D E A D E The winner may be in the
183     * A B C E B C A E 2 players or the 3 players
184     * A C B A group. In either case, a
185     * A A second player must be choosen
186     * to be either the one playing
187     * against A in the 2-players subtree or being the winner
188     * of the 2-player subtree if A is in the 3-players subtree.
189     */
190    
191     static double five_player(unsigned int *rating)
192     {
193     unsigned int a,b,c,d,e;
194    
195     a = rating[0];
196     b = rating[1];
197     c = rating[2];
198     d = rating[3];
199     e = rating[4];
200    
201     return (five_f1(a,b,c,d,e)+five_f1(a,c,d,e,b)+
202     five_f1(a,d,e,b,c)+five_f1(a,e,b,c,d))/30;
203     }
204    
205     /* [Denis MOREAUX <vapula@linuxbe.org>, 10 Apr 2000
206     *
207     * Two cases to treat : AB-CDE and BC-ADE.
208     * in both cases, A win against B.
209     * In the first case, A win over the winner of a 3-players game
210     * (3 possible winners).
211     * In the second case, B win over one of the three other and A is in
212     * the 3-players game.
213     */
214    
215     static double five_f1(int a, int b, int c, int d, int e)
216     {
217     double ab,ac,ad,ae,bc,bd,be;
218    
219     ab = probability(a,b);
220     ac = probability(a,c);
221     ad = probability(a,d);
222     ae = probability(a,e);
223     bc = probability(b,c);
224     bd = probability(b,d);
225     be = probability(b,e);
226    
227     return ab*(ac*five_f2(c,d,e)+ad*five_f2(d,e,c)+ae*five_f2(e,c,d)+
228     bc*five_f2(a,d,e)+bd*five_f2(a,c,e)+be*five_f2(a,c,d));
229     }
230    
231     static double five_f2(int a, int b, int c)
232     {
233     double ab,ac,bc,cb;
234    
235     ab = probability(a,b);
236     ac = probability(a,c);
237     bc = probability(b,c);
238     cb = 1.0 - bc;
239    
240     return (2*(ab*ac)+bc*ab+cb*ac);
241     }
242    
243    
244     static double six_player(unsigned int *rating)
245     {
246     unsigned int a,b,c,d,e,f;
247    
248     a = rating[0];
249     b = rating[1];
250     c = rating[2];
251     d = rating[3];
252     e = rating[4];
253     f = rating[5];
254    
255     /* A B C D
256     * A C E F
257     * A E
258     * A
259     */
260    
261     return (six_f1(a,b,c,d,e,f)+ /* A is in group of 4 */
262     six_f1(a,b,c,e,d,f)+
263     six_f1(a,b,e,d,c,f)+
264     six_f1(a,e,c,d,b,f)+
265     six_f1(a,b,c,f,d,e)+
266     six_f1(a,b,f,d,c,e)+
267     six_f1(a,f,c,d,b,e)+
268     six_f1(a,e,f,b,c,d)+
269     six_f1(a,e,f,c,b,d)+
270     six_f1(a,e,f,d,b,c)+
271     six_f2(a,b,c,d,e,f)+ /* A is in group of 2 */
272     six_f2(a,c,b,d,e,f)+
273     six_f2(a,d,b,c,e,f)+
274     six_f2(a,e,b,c,d,f)+
275     six_f2(a,f,b,c,d,e))/45;
276     }
277    
278    
279     /* ABCD = group of 4, EF = group of 2, A must win */
280     /* D.Moreaux, 10 Apr 2000: changed double to int for the parameters */
281    
282     static double six_f1(int a, int b, int c, int d, int e, int f)
283     {
284     double ab,ac,ad,bc,bd,cb,cd,db,dc,ef,fe,ae,af;
285    
286     ab = probability(a,b);
287     ac = probability(a,c);
288     ad = probability(a,d);
289     ae = probability(a,e);
290     af = probability(a,f);
291     bc = probability(b,c);
292     bd = probability(b,d);
293     cd = probability(c,d);
294     ef = probability(e,f);
295     cb = 1.0 - bc;
296     db = 1.0 - bd;
297     dc = 1.0 - cd;
298     fe = 1.0 - ef;
299     return (ab*ac*(cd+bd)+ac*ad*(db+cb)+ab*ad*(dc+bc))*(ef*ae+fe*af);
300     }
301    
302    
303     /* AB is group of 2, CDEF is group of 4, A must win */
304    
305     static double six_f2(int a, int b, int c, int d, int e, int f)
306     {
307     double ab,ac,ad,ae,af;
308    
309     ab = probability(a,b);
310     ac = probability(a,c);
311     ad = probability(a,d);
312     ae = probability(a,e);
313     af = probability(a,f);
314    
315     return (six_f3(c,d,e,f)*ab*ac+
316     six_f3(d,c,e,f)*ab*ad+
317     six_f3(e,c,d,f)*ab*ae+
318     six_f3(f,c,d,e)*ab*af);
319     }
320    
321    
322     /* ABCD is group of 4, A win */
323    
324     static double six_f3(int a, int b, int c, int d)
325     {
326     double ab,ac,ad,bc,bd,cb,cd,db,dc;
327    
328     ab = probability(a,b);
329     ac = probability(a,c);
330     ad = probability(a,d);
331     bc = probability(b,c);
332     bd = probability(b,d);
333     cd = probability(c,d);
334     cb = 1.0 - bc;
335     db = 1.0 - bd;
336     dc = 1.0 - cd;
337    
338     return (ab*ac*(cd+bd)+ac*ad*(db+cb)+ab*ad*(dc+bc));
339     }
340    
341    
342     static double seven_player(unsigned int *rating)
343     {
344     unsigned int a,b,c,d,e,f,g;
345    
346     a = rating[0];
347     b = rating[1];
348     c = rating[2];
349     d = rating[3];
350     e = rating[4];
351     f = rating[5];
352     g = rating[6];
353    
354     return (seven_f1(a,b,c,d,e,f,g)+seven_f1(a,c,b,d,e,f,g)+
355     seven_f1(a,d,c,b,e,f,g)+seven_f1(a,e,c,d,b,f,g)+
356     seven_f1(a,f,c,d,e,b,g)+seven_f1(a,g,c,d,e,f,b))/45;
357     }
358    
359     static double seven_f1(int a, int b, int c, int d, int e, int f, int g)
360     {
361    
362     return seven_f2(a,b,c,d,e,f,g)+seven_f2(a,b,d,c,e,f,g)+
363     seven_f2(a,b,e,d,c,f,g)+seven_f2(a,b,f,d,e,c,g)+
364     seven_f2(a,b,g,d,e,f,c);
365     }
366    
367     static double seven_f2(int a, int b, int c, int d, int e, int f, int g)
368     {
369     double ab,ac,ad,ae,af,ag,bc,bd,be,bf,bg,cd,ce,cf,cg;
370     double de,df,dg,ed,ef,eg,fd,fe,fg,gd,ge,gf;
371     ab = probability(a,b);
372     ac = probability(a,c);
373     ad = probability(a,d);
374     ae = probability(a,e);
375     af = probability(a,f);
376     ag = probability(a,g);
377     bc = probability(b,c);
378     bd = probability(b,d);
379     be = probability(b,e);
380     bf = probability(b,f);
381     bg = probability(b,g);
382     cd = probability(c,d);
383     ce = probability(c,e);
384     cf = probability(c,f);
385     cg = probability(c,g);
386     de = probability(d,e);
387     df = probability(d,f);
388     dg = probability(d,g);
389     ef = probability(e,f);
390     eg = probability(e,g);
391     fg = probability(f,g);
392     ed = 1.0 - de;
393     fd = 1.0 - df;
394     gd = 1.0 - dg;
395     fe = 1.0 - ef;
396     ge = 1.0 - eg;
397     gf = 1.0 - fg;
398    
399     return
400     ab*(
401     (ac+bc)*
402     (ad*(de*df*(fg+eg)+df*dg*(ge+fe)+de*dg*(gf+ef))+ /* 4:d win */
403     ae*(ed*ef*(fg+dg)+ef*eg*(gd+fd)+ed*eg*(gf+df))+ /* 4:e win */
404     af*(fe*fd*(dg+eg)+fd*fg*(ge+de)+fe*fg*(gd+ed))+ /* 4:f win */
405     ag*(ge*gf*(fd+ed)+gf*gd*(de+fe)+ge*gd*(df+ef)))+ /* 4:g win */
406     bc*
407     ((bd+cd)*(ae*af*(fg+eg)+af*ag*(ge+fe)+ae*ag*(gf+ef))+ /* 3:d */
408     (be+ce)*(ad*af*(fg+dg)+af*ag*(ad+ad)+ad*ag*(gf+df))+ /* 3:e */
409     (bf+cf)*(ae*ad*(dg+eg)+ad*ag*(ge+de)+ae*ag*(gd+ed))+ /* 3:f */
410     (bg+cg)*(ae*af*(fd+ed)+af*ad*(de+fe)+ae*ad*(df+ef)))); /* 3:g */
411    
412     }
413    
414     static double eight_player(unsigned int *rating)
415     {
416     unsigned int a,b,c,d,e,f,g,h;
417     double ab,ac,ad,ae,af,ag,ah;
418    
419     a = rating[0];
420     b = rating[1];
421     c = rating[2];
422     d = rating[3];
423     e = rating[4];
424     f = rating[5];
425     g = rating[6];
426     h = rating[7];
427    
428     ab = probability(a,b);
429     ac = probability(a,c);
430     ad = probability(a,d);
431     ae = probability(a,e);
432     af = probability(a,f);
433     ag = probability(a,g);
434     ah = probability(a,h);
435    
436     /* First against A may be one from seven */
437    
438     return (eight_f1(a,c,d,e,f,g,h)*ab+
439     eight_f1(a,b,d,e,f,g,h)*ac+
440     eight_f1(a,b,c,e,f,g,h)*ad+
441     eight_f1(a,b,c,d,f,g,h)*ae+
442     eight_f1(a,b,c,d,e,g,h)*af+
443     eight_f1(a,b,c,d,e,f,h)*ag+
444     eight_f1(a,b,c,d,e,f,g)*ah)/315;
445    
446     }
447    
448    
449     static double eight_f1(int a, int b, int c, int d, int e, int f, int g)
450     {
451     /* The winner of the second group, who'll then play against A, may be one
452     from six possible players */
453    
454     return eight_f2(a,b,c,d,e,f,g)+
455     eight_f2(a,c,b,d,e,f,g)+
456     eight_f2(a,d,b,c,e,f,g)+
457     eight_f2(a,e,b,c,d,f,g)+
458     eight_f2(a,f,b,c,d,e,g)+
459     eight_f2(a,g,b,c,d,e,f);
460     }
461    
462     static double eight_f2(int a, int b, int c, int d, int e, int f, int g)
463     {
464     double ab,bc,bd,be,bf,bg;
465    
466     ab = probability(a,b);
467     bc = probability(b,c);
468     bd = probability(b,d);
469     be = probability(b,e);
470     bf = probability(b,f);
471     bg = probability(b,g);
472    
473     /* There are 5 player who may play against the 3rd. The third (b) will win
474     over them and lose against a */
475    
476     return ab*(eight_f3(a,d,e,f,g)*bc+
477     eight_f3(a,c,e,f,g)*bd+
478     eight_f3(a,c,d,f,g)*be+
479     eight_f3(a,c,d,e,g)*bf+
480     eight_f3(a,c,d,e,f)*bg);
481    
482     }
483    
484     /* D.Moreaux, 10 Apr 2000: changed double to int for the parameters */
485    
486     static double eight_f3(int a, int b, int c, int d, int e)
487     {
488     double ab,ac,ad,ae,bc,bd,be,cb,cd,ce,db,dc,de,eb,ec,ed;
489    
490     ab = probability(a,b);
491     ac = probability(a,c);
492     ad = probability(a,d);
493     ae = probability(a,e);
494     bc = probability(b,c);
495     bd = probability(b,d);
496     be = probability(b,e);
497     cd = probability(c,d);
498     ce = probability(c,e);
499     de = probability(d,e);
500     cb = 1.0 - bc;
501     db = 1.0 - bd;
502     dc = 1.0 - cd;
503     eb = 1.0 - be;
504     ec = 1.0 - ce;
505     ed = 1.0 - de;
506    
507     /* expansion then factorisation (this function is called 210 times)
508     * gain 4 func_call
509     * 24 *
510     * 30 probability
511     */
512     return (bc*de+be*dc)*((ab-ad)*bd+ad)+
513     (bd*ce+be*cd)*((ab-ac)*bc+ac)+
514     (cb*de+db*ce)*((ac-ad)*cd+ad)+
515     (cd*eb+cb*ed)*((ac-ae)*ce+ae)+
516     (dc*eb+db*ec)*((ad-ae)*de+ae)+
517     (bd*ec+bc*ed)*((ae-ab)*eb+ab);
518     }
519    
520     /* Determine changes in ratings due to game results. */
521     extern int ladder_calc_info(t_clienttag clienttag, t_ladder_id id, unsigned int count, t_account * * players, t_game_result * results, t_ladder_info * info)
522     {
523     unsigned int curr;
524     unsigned int *rating;
525     unsigned int *sorted;
526    
527     if (!players)
528     {
529     eventlog(eventlog_level_error,__FUNCTION__,"got NULL players");
530     return -1;
531     }
532     if (!results)
533     {
534     eventlog(eventlog_level_error,__FUNCTION__,"got NULL results");
535     return -1;
536     }
537     if (!clienttag)
538     {
539     eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag");
540     return -1;
541     }
542     if (!info)
543     {
544     eventlog(eventlog_level_error,__FUNCTION__,"got NULL info");
545     return -1;
546     }
547    
548     rating = xmalloc(sizeof(unsigned int)*count);
549     sorted = xmalloc(sizeof(unsigned int)*count);
550    
551     for (curr=0; curr<count; curr++)
552     rating[curr] = account_get_ladder_rating(players[curr],clienttag,id);
553    
554     for (curr=0; curr<count; curr++)
555     {
556     double k;
557     double prob;
558     double delta;
559     t_game_result myresult;
560     unsigned int opponent_count;
561     unsigned int team_members;
562    
563     k = coefficient(players[curr],clienttag,id);
564     opponent_count = 0;
565     myresult = results[curr];
566    
567     {
568     unsigned int i,j;
569    
570     /* Put the current user into slot 0, his opponents into other slots
571     order is not important for the other players */
572     for (i=0,j=1; i<count; i++)
573     if (i==curr)
574     sorted[0] = rating[i];
575     else
576     {
577     if (results[i]!=myresult)
578     {
579     sorted[j++] = rating[i];
580     opponent_count++;
581     }
582     }
583     }
584    
585     team_members = count - opponent_count;
586    
587     switch (opponent_count)
588     {
589     case 1:
590     prob = two_player(sorted);
591     break;
592     case 2:
593     prob = three_player(sorted);
594     break;
595     case 3:
596     prob = four_player(sorted);
597     break;
598     case 4:
599     prob = five_player(sorted);
600     break;
601     case 5:
602     prob = six_player(sorted);
603     break;
604     case 6:
605     prob = seven_player(sorted);
606     break;
607     case 7:
608     prob = eight_player(sorted);
609     break;
610     default:
611     eventlog(eventlog_level_error,__FUNCTION__,"sorry, unsupported number of ladder opponents (%u)",opponent_count);
612     xfree((void *)rating);
613     xfree((void *)sorted);
614     return -1;
615     }
616    
617     if (results[curr]==game_result_win)
618     delta = fabs(k * (1.0 - prob) / team_members); /* better the chance of winning -> fewer points added */
619     else
620     delta = -fabs(k * prob); /* better the chance of winning -> more points subtracted */
621    
622     eventlog(eventlog_level_debug,__FUNCTION__,"computed probability=%g, k=%g, deltar=%+g",prob,k,delta);
623    
624     info[curr].prob = prob;
625     info[curr].k = (unsigned int)k;
626     info[curr].adj = (int)delta;
627     info[curr].oldrating = rating[curr];
628     info[curr].oldrank = account_get_ladder_rank(players[curr],clienttag,id);
629     }
630    
631     xfree((void *)rating);
632     xfree((void *)sorted);
633    
634     return 0;
635     }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1