Ptahhotep's Team Balancer (PTB)
Version 1.7 BETA

DATE: February 9, 2003
AUTHOR: Ptahhotep (ptahhotep@planethalflife.com)

PTB ported to AMX Mod by OLO
PTB updated to CS 1.6 by XAD
PTB ported to AMXmodX by XAD

Comments On Version 1.7
-----------------------
o This version adds another feature to PTB, which scales down the
  the internally counted player scores. If the sum of kills and
  deaths for a player exceed PTB_MAXINCIDENTS, the scores are
  divided by PTB_SCALEDOWN. This insures, that consecutive kills
  or deaths of a player have a higher influence on his kills/deaths
  ratio. A single kill of a player with a 500/300 score would mean
  nothing. The new system insures, that this score would be
  represented by an equivalent 25/15 or similar and every consecutive
  kill or death would influence the ratio noticibly. That way the
  rating of a player is representing the player's current performance
  way better in long games (read: dust-only over 7 hours ...).
o There reported some problems with servers running for 18 hours
  or more. PTB started reporting stack overflows (amx error 3) at
  each kill. This version should resolve these problems, since the
  source of the error (AdminMod's native function playerinfo) is
  now either not used anymore or feeded very carefully. If that
  doesn't help, it's possible to get rid of the stack overflow
  problem with an increase of the stack frame (change the according
  line in the script to #pragma dynamic 262144 and recompile).

Comments On Version 1.6
-----------------------
o This version adds another 8 new configuration options to PTB.
o Setting the new max team size setting to a number smaller than half
  the number of maximum players on the server effectively forces the
  remaining players into spectator mode.
o I put some real work into the amx_ptb command. Please check out
  the "amx_ptb" and "amx_ptb status" commands from the CS console.
o PTB now limits the frequency of switches of individual players,
  which should help getting rid of complaints about frequent switching.
o PTB 1.6 uses the AdminMod playercount() function to determine
  the current number of players in the game. The number returned by
  that function is not always correct. Please keep that in mind when
  using the new PTB_SWITCHMIN and PTB_LIMITMIN settings. You can
  monitor the value returned by playerinfo() by typing amx_ptb in
  the console. I also tried to track the number of connections and
  disconnections, but that gives even worse results, since AdminMod
  doesn't seem to generate either enough disconnect or more than
  enough connect events.
o The new commands "amx_ptb save" and "amx_ptb load" let you
  save and restore changes in the settings made from the console.
  That way you can experiment with the PTB settings in-game and
  make them permanent without editing any files by hand.
o The new PTB_SUPERRATING setting adds a new winning team condition,
  that effectively limits the maximum allowed team strength for the
  losing team. Before version 1.6 PTB allowed a team to be as strong
  as it gets, as long as it didn't have either a winning streak or
  a score advantage or both. See the Details section for details.
o The new commands "amx_ptb list" and "amx_ptb help" both give
  you a brief overview of available PTB commands.

Comments On Version 1.5
-----------------------
This verion of PTB is tested with AdminMod 2.50.26a, Metamod 1.12
and LogD 1.00.3 (Wraith's version ...).
This version improves PTB in a lot of ways:
o Most important is the new team switching code, which looks
  for the best possible switch to execute. If there is no switch
  that makes any difference in team balance, no switching happens.
  Thanks go to NtroP for pushing me to finish his team
  switching code for version 1.5 of PTB.
o Also new is an improved team strength calculation method,
  providing better indication of team strength. A detailed
  description is given in the Details section.
o Players will not be allowed to choose their team in the first
  3 rounds, instead they will be auto-joined.
o PTB will now try to keep the differences in team size below 3
  when auto-joining players.
o Forcing a switch (switching alive) is now configurable. You
  can set the number of unsuccessful tries, after which PTB
  does a switch of living players (killing them in the process).
o Default settings for wtj auto-joining and kicking are much
  more strict now. Try wtjing a second time and PTB will auto-
  join you, try it a third time and you get kicked.
o There is now an option to disable typesays completely.
o All the things above are configurable through "vault.ini" -
  another new feature of PTB 1.5.
o Finally some bugs were fixed and some additional changes might
  have happened that I forgot to note.
See the latest changes notes below and the new section about
vault.ini for more details.

Introduction
------------
This version of PTB is an AMX plugin (http://amxmod.net).
PTB is a Counter-Strike (CS) specific plugin.

To run PTB with its default settings, simply compile it
for your operating system, include it into plugins.ini
and change the map on your CS server.

PTB detects situations, in which one team rules over the other.
It looks at the current team scores, current team win streaks
and the current team ratings and decides on actions with the
help of these values.

Additionally PTB completely controls team joining actions of
players and prevents unbalancing team joins. PTB auto-joins
and even kicks obvious winning team joiners.

Features
--------
o team strength evaluation based on scores, streaks, kills, deaths and size
o search for best balancing switch or transfer
o automatic dead only team switches
o automatic dead only team transfers
o announcement of team balance status
o display of WTJ attempts
o prevention, auto-join and kick for WTJing
o "safe auto-join" - overriden auto-join function, that is always
  choosing the right team and prevents joining of the same or
  winning or bigger team, using auto-team never kills a player,
  if he can't switch teams, and never gives WTJ counts
o controllable with 33 console commands
o configurable with 26 configuration options
o configurable through vault.ini
o much more ...

Details
-------
The most important thing PTB evaluates is team strength. PTB calculates
a single number as an indicator of team strength.

In PTB 1.5 the team strength calculation changed. In earlier versions,
team strength was calculated as the sum of total kills per team over the
sum of total deaths per team times the number of players per team
(strength = kills/deaths * players). The method didn't always work well,
since a very good player (20:1) and a very bad player (1:20) made no
difference to 2 mediocre players (5:5 and 6:6).

The new method calculates a separate kills/deaths ratio per player, sums
the ratios up per team and multiplies them with team size
(strength = players * (sum of kills/deaths per player)).

 Example:
 CT team: A (6:5), B (2:3)
 T team: C (1:1), D (4:3), E (1:4)
 CT strength: 2 * (6/5 + 2/3) = 3.73
 T strength: 3 * (1/1 + 4/3 + 1/4) = 7.75

To compare the team strengths against each other, a rating is calculated
per team by dividing the team's	strength by the opposing team's strength
(rating = ownStrength / opposingStrength).

 Example (continued):
 CT rating: 3.73/7.75 = 0.48
 T rating: 7.75/3.73 = 2.08

Just in case you want to know: the old ratings would have been 0.88 for
the CT team and 1.125 for the T team. Just imagine to add player F (0:10)
to the CT team and look what happens to the old and new ratings. I found
the new ratings to represent the teams much better.

But team rating is not all. Even the best team might fail. That's why PTB
doesn't limit itself to those kill/death ratios. PTB also compares the number
of team wins and notes the number of consecutive rounds one by a team as
additional indicators for team efficiency.

To decide, if there if there is a winning team situation, PTB then evaluates
the following equations:

o team rating >= PTB_MINRATING (stronger team) and score > PTB_MAXDIFF
o team rating >= PTB_MINRATING (stronger team) and streak > PTB_MAXSTREAK
o team rating >= PTB_MINRATING (stronger team) and more players
o team rating >= PTB_MAXRATING (way stronger team)
o team rating >= PTB_SUPERRATING (overwhelming team strength)

If any TWO of these criteria hold for one team, it is considered to
be the winning team and actions are taken as appropriate.

Note: Teams with a rating below PTB_MINRATING are considered as of equal
or very similar strength. If team strengths are very similar, streaks
and	scores are ignored. As soon as a team gets noticibly stronger
than it's opposing team, scores, streaks and team size are checked.

PTB balances the teams in one of two ways. If the losing team is smaller,
PTB transfers a player from the winning to the losing team. Else two players
are exchanged (switched) with each other. Valid targets for switches and
transfers are dead players and players, who didn't change teams already
this round. These limitations origin from the fact, that it's not possible
to switch a living player with the help of console commands without killing
him. Additionally CS currently does allow only one team change per round.
Since PTB 1.5 all possible transfers or switches are evaluated for the
switch or tranfer, that balances the teams the most. If no switch or transfer
would improve team balance, switching or transfering is skipped.

Configuration
-------------
PTB Required Variable Settings:
mp_autoteambalance 0 - switch off inbuild CS team balancing
mp_limitteams 0 - disable team size difference limit

PTB Commands for admins with ADMIN_RCON access:

// misc
amx_ptb - show PTB statistics
amx_ptb status - show all current settings
amx_ptb list - list of ptb commands
amx_ptb help - same as "list"
amx_ptb on - enable all options
amx_ptb off - disable all options

// team selection control
amx_ptb limitjoin on|off (default: on) - team join control
amx_ptb limitafter <value> (default: 0) - rounds after which teams limiting begins
amx_ptb limitmin <value> (default: 0) - minimum players for team limiting
amx_ptb maxsize <value> (default: 10) - maximum team size per team
amx_ptb autorounds <value> (default: 3) - initial rounds without free team choice
amx_ptb maxdiff <value> (default: 2) - maximum accepted team size difference
amx_ptb wtjauto <value> (default: 3) - WTJ tries for auto-join
amx_ptb wtjkick <value> (default: 5) - WTJ tries for kick
amx_ptb kick on|off (default: on) - WTJ kicking
amx_ptb savewtj on|off (default: off) - wtj.log writing

// team balancing actions
amx_ptb switch on|off (default: on) - team switching and transfers
amx_ptb switchafter <value> (default: 0) - rounds after which switching begins
amx_ptb switchmin <value> (default: 3) - minimum players on map for switching
amx_ptb switchfreq <value> (default: 1) - maximum team switching frequency
amx_ptb playerfreq <value> (default: 3) - maximum player switching frequency
amx_ptb forceswitch <value> (default: 3) - forced switch delay (switching alive, if neccessary)
amx_ptb deadonly on|off (default: off) - switch dead only or alive, too

// messages
amx_ptb tellwtj on|off (default: on) - tell about wtj tries
amx_ptb announce on|off (default: on) - announcements
amx_ptb sayok on|off (default: on) - "no action required" message
amx_ptb typesay on|off (default: on) - globally switch use of typesay

// team strength limits
amx_ptb maxstreak <value> (default: 2) - maximum accepted team win streak
amx_ptb maxscore <value> (default: 2) - maximum accepted team score difference
amx_ptb minrating <value> (default: 1.5) - stronger team, if rating >= minrating
amx_ptb maxrating <value> (default: 2.0) - way stronger team, if rating >= maxrating
amx_ptb superrating <value> (default: 3.0) - overwhelming team strength, if rating >= superrating
amx_ptb maxincidents <value> (default: 50) - maximum incidents per player before scale down
amx_ptb scaledown <value> (default: 2) - scale down factor for player incidents
 (don't play with these, if you don't fully understand, what they mean)

Configuration Using "ptb.cfg"
-------------------------------
PTB options can be set by manipulating the variables at
the top of the code or by setting variables in ptb.cfg
configuration file placed in cstrike/addons/amxx/custom/ path.
You can type "amx_ptb status" in the console of a running CS
server to get some info on the settings. On every map change
this file is autoexecuted by the PTB plugin.

// these two cvars must be set to 0 for PTB proper working
mp_autoteambalance 	0
mp_limitteams 		0

// team selection control
amx_ptb limitjoin    on 	// set limits on team joining
amx_ptb limitafter   0		// number of rounds after which teams limiting begins
amx_ptb limitmin     0		// number of minimum players on map for team limiting
amx_ptb maxsize      10		// maximum team size per team
amx_ptb maxdiff      2		// maximum team size difference
amx_ptb autorounds   0		// number of first rounds into match, which allow autojoin only
amx_ptb wtjauto      3		// wtj tries needed to become autojoined
amx_ptb wtjkick      5		// wtj tries needed to become kicked
amx_ptb kick         off	// kick for wtj counts
amx_ptb savewtj      off	// save wtjs to wtj.log

// team balancing actions
amx_ptb switch       on		// switch/transfer players
amx_ptb switchafter  0		// number of rounds after which switching begins
amx_ptb switchmin    3		// number of minimum players on map for switching
amx_ptb switchfreq   1		// relative next possible switch round
amx_ptb playerfreq   3		// relative next possible switch round for player
amx_ptb forceswitch  2		// number of tries after which PTB switches alive, if neccessary
amx_ptb deadonly     off	// switch dead only

// messages
amx_ptb tellwtj      on		// tell about wtj tries
amx_ptb announce     on		// announce team status at beginning of round
amx_ptb sayok        on		// announce team status, if teams are alright
amx_ptb typesay      on		// use HUD messages

// team strength limits
amx_ptb maxstreak    2		// max. allowed team win streak
amx_ptb maxscore     2		// max. allowed team score difference
amx_ptb minrating    1.5	// minimum critical team rating
amx_ptb maxrating    2.0	// maximum critical team rating
amx_ptb superrating  3.0	// super critical team rating
amx_ptb maxincidents 50		// maximum kills + deaths before the score is divided by PTB_SCALEDOWN
amx_ptb scaledown    2		// divisor for kills and deaths, when PTB_MAXINCIDENTS is reached

