1 /* bzflag
2 * Copyright (c) 1993-2021 Tim Riker
3 *
4 * This package is free software; you can redistribute it and/or
5 * modify it under the terms of the license found in the file
6 * named COPYING that should have accompanied this file.
7 *
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12
13 /* interface header */
14 #include "Score.h"
15 #include "bzfsAPI.h"
16 #include "WorldEventManager.h"
17 #include "GameKeeper.h"
18 #include "bzfs.h"
19
20 // bzflag library headers
21 #include "Pack.h"
22
23 // API headers for notification
24
25 float Score::tkKickRatio = 3.0;
26 int Score::score = 999;
27 bool Score::randomRanking = false;
28
29 bool Score::KeepPlayerScores = true;
30 bool Score::KeepTeamScores = true;
31
Score()32 Score::Score(): wins(0), losses(0), tks(0), handicap(0)
33 {
34 playerID = -1;
35 }
36
dump()37 void Score::dump()
38 {
39 std::cout << wins << '-' << losses;
40 }
41
ranking()42 float Score::ranking()
43 {
44 if (randomRanking)
45 return (float)bzfrand();
46
47 // otherwise do score-based ranking
48 int sum = wins + losses;
49 if (sum == 0)
50 return 0.5;
51 float average = (float)wins/(float)sum;
52 // IIRC that is how wide is the gaussian
53 float penalty = (1.0f - 0.5f / sqrt((float)sum));
54 return average * penalty;
55 }
56
isTK() const57 bool Score::isTK() const
58 {
59 // arbitrary 3
60 return (tks >= 3) && (tkKickRatio > 0)
61 && ((wins == 0) || (tks * 100 / wins > tkKickRatio));
62 }
63
64 // Change a score element, then call an event
changeScoreElement(bz_eScoreElement element,int * toChange,int newValue)65 void Score::changeScoreElement(bz_eScoreElement element, int *toChange, int newValue)
66 {
67 int oldValue = *toChange;
68 *toChange = newValue;
69 bz_PlayerScoreChangeEventData_V1 eventData = bz_PlayerScoreChangeEventData_V1(playerID, element, oldValue, newValue);
70 worldEventManager.callEvents(&eventData);
71 }
72
73
tK()74 void Score::tK()
75 {
76 if (KeepPlayerScores)
77 changeScoreElement(bz_eTKs, &tks, tks + 1);
78 }
79
killedBy()80 void Score::killedBy()
81 {
82 if (KeepPlayerScores)
83 changeScoreElement(bz_eLosses, &losses, losses + 1);
84 }
85
kill()86 void Score::kill()
87 {
88 if (KeepPlayerScores)
89 changeScoreElement(bz_eWins, &wins, wins + 1);
90 }
91
92
reset()93 void Score::reset()
94 {
95 changeScoreElement(bz_eWins, &wins, 0);
96 changeScoreElement(bz_eLosses, &losses, 0);
97 changeScoreElement(bz_eTKs, &tks, 0);
98 }
99
pack(void * buf)100 void *Score::pack(void *buf)
101 {
102 buf = nboPackUShort(buf, wins);
103 buf = nboPackUShort(buf, losses);
104 buf = nboPackUShort(buf, tks);
105 return buf;
106 }
107
reached() const108 bool Score::reached() const
109 {
110 return wins - losses >= score;
111 }
112
setTeamKillRatio(int _tkKickRatio)113 void Score::setTeamKillRatio(int _tkKickRatio)
114 {
115 tkKickRatio = (float)_tkKickRatio;
116 }
117
setWinLimit(int _score)118 void Score::setWinLimit(int _score)
119 {
120 score = _score;
121 }
122
setRandomRanking()123 void Score::setRandomRanking()
124 {
125 randomRanking = true;
126 }
127
128 // Local Variables: ***
129 // mode: C++ ***
130 // tab-width: 4 ***
131 // c-basic-offset: 4 ***
132 // indent-tabs-mode: nil ***
133 // End: ***
134 // ex: shiftwidth=4 tabstop=4
135