Announcement

Collapse
No announcement yet.

Next League

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Rab
    replied
    I already have solutions to the ratings and drafting systems for TSL, did this ages ago it just never got implemented.

    Ratings
    The formulas in this thread produce dollar-values that can be compared between divisions and between basing ships.
    https://forums.trenchwars.com/forum/...ula-discussion

    Drafting
    This is a sample of code from an automated drafter. It picks basing teams like a real captain would, e.g. if you pick a shark and there aren't many sharks I pick a shark. Can provide the full code if needed for someone to actually implement it.
    Code:
    using DraftLibrary.Classes;
    using System.Collections.Generic;
    using System;
    using System.Linq;
    
    namespace DraftLibrary.Algorithms
    {
        class Snake
        {
            public static List<Team> DraftWithCaptain(List<Player> players, List<Team> teams)
            {
                //// the snake format is still fine for picking with a captain
                //// it gives the captains a turn in the correct order, like TWDT
    
                List<int> draftOrder = GetDraftOrder(players, teams);
    
                for (int i = 0; i < draftOrder.Count; i++)
                {
                    int teamIndex = draftOrder[i];
    
                    Team currentTeam = teams[teamIndex];
    
                    ////
                    //// I am ALL CAPS picking against ALL THE OTHERS
                    //// 
                    //// work out who we should pick
                    //// we need 1 terr, 2 sharks, 5 spiders
                    //// we know which team we're up against
                    Team opponentTeam = (teamIndex % 2) == 0 ? teams[teamIndex + 1] : teams[teamIndex - 1];
                    //// we have overall, terr, shark, spid ratings.
    
                    // see who's left to pick
                    List<Player> remaining = GetPlayersRemaining(players, teams);
    
                    //// someone might end up in multiple lists, e.g. turban, dreamwin
    
                    // be less selective as the draft progresses.
                    int round = (i + teams.Count) / teams.Count;
    
                    // some constants which vary depending on the ratings used
                    int HighestUsefulRating = 7; /* e.g. 7* at something is worth prioritising over their Overall rating, 6* isn't. */
                    int EliteRating = 10; /* you want to be picking a 10* first */
                    int RoundRelaxation = 1; /* each round, including round 1, reduce pickyness by 1* */
                    // ^ the point of this is that you don't really want to be picking an 8* over a 9/10* in round 1, but in round 2 you might.
    
                    // shortlist remaining sharks
                    List<Player> sharkShortlist = ShortlistSharks(remaining, Math.Max(HighestUsefulRating, EliteRating - (round * RoundRelaxation)));
    
                    // shortlist remaining terrs
                    List<Player> terrShortlist = ShortlistTerrs(remaining, Math.Max(HighestUsefulRating, EliteRating - (round * RoundRelaxation)));
    
                    // shortlist remaining spiders
                    List<Player> spiderShortlist = ShortlistSpiders(remaining, Math.Max(HighestUsefulRating, EliteRating - (round * RoundRelaxation)));
    
                    // I need to know how many turns until my next pick
                    bool haveAnotherPick = false;
                    int turnsUntilNextPick = 0;
                    for (int j = i + 1; j < draftOrder.Count; j++)
                    {
                        if (teamIndex == draftOrder[j])
                        {
                            haveAnotherPick = true;
                            turnsUntilNextPick = j - i;
                            break;
                        }
                    }
    
                    List<Player> solidPicks = new List<Player>();
    
                    if (
                        /* dont pick more than 2 sharks */
                        currentTeam.Sharks.Count < 2
                        /* this logic only works if we have shortlisted sharks available */
                        && sharkShortlist.Count > 0
                        && (
                            /* don't get out sharked */
                            currentTeam.Sharks.Count <= opponentTeam.Sharks.Count
                            /* if you're concerned someone else is going to snipe your shark pick */
                            || (haveAnotherPick && sharkShortlist.Count < turnsUntilNextPick)
                            )
                        )
                    {
                        Player player = GetHighestRatedShark(sharkShortlist);
    
                        if (!solidPicks.Contains(player))
                        {
                            player.Context = "Shark";
                            solidPicks.Add(player);
                        }
                    }
    
                    if (
                       /* don't pick more than 1 terr */
                       currentTeam.Terr.Count < 1
                       /* this logic only works if we have shortlisted terrs available */
                       && terrShortlist.Count > 0
                       && (
                           /* don't get out terred */
                           currentTeam.Terr.Count <= opponentTeam.Terr.Count
                           /* if you're concerned someone else is going to snipe your terr pick */
                           || (haveAnotherPick && terrShortlist.Count < turnsUntilNextPick)
                           )
                       )
                    {
                        Player player = GetHighestRatedTerr(terrShortlist);
    
                        if (!solidPicks.Contains(player))
                        {
                            player.Context = "Terr";
                            solidPicks.Add(player);
                        }
                    }
    
                    if (
                        /* don't pick more than 5 spiders */
                        currentTeam.Spids.Count < 5
                        /* this logic only works if we have shortlisted spiders available */
                        && spiderShortlist.Count > 0
                        && (
                                /* don't get out spidered */
                                currentTeam.Spids.Count <= opponentTeam.Spids.Count
                                /* if you're concerned someone else is going to snipe your spider pick */
                                || (haveAnotherPick && spiderShortlist.Count < turnsUntilNextPick)
                            )
                        )
                    {
                        Player player = GetHighestRatedSpider(spiderShortlist);
    
                        if (!solidPicks.Contains(player))
                        {
                            player.Context = "Spid";
                            solidPicks.Add(player);
                        }
                    }
    
                    Player pick = null;
    
                    if (solidPicks.Count == 1)
                    {
                        // We found 1 solid pick, just add it.
                        pick = solidPicks[0];
    
                    }
                    else if (solidPicks.Count > 1)
                    {
                        // There's more than 1 player we'd like to pick
                        // We have to resolve it somehow... prefer the default order, but let higher rating override it.
                        Player player = GetHighestRatedSolidPick(solidPicks);
                        pick = player;
                    }
                    else
                    {
                        // fallback, just pick the highest overall rated player
                        Player player = GetHighestRatedPlayer(remaining);
                        player.Context = string.Empty;
                        pick = player;
                    }
    
                    switch (pick.Context)
                    {
                        case "Terr":
                            currentTeam.AddTerr(pick);
                            break;
                        case "Shark":
                            currentTeam.AddShark(pick);
                            break;
                        case "Spid":
                            currentTeam.AddSpid(pick);
                            break;
                        default:
                            currentTeam.AddPlayer(pick);
                            break;
                    }
                }
    
                return teams;
            }
    
            private static Player GetHighestRatedSpider(List<Player> spiders)
            {
                Player player = null;
    
                foreach (Player p in spiders)
                {
                    if (player == null) player = p;
    
                    if (p.Spid > player.Spid) player = p;
                }
    
                return player;
            }
    
            private static Player GetHighestRatedTerr(List<Player> terrs)
            {
                Player player = null;
    
                foreach (Player p in terrs)
                {
                    if (player == null) player = p;
    
                    if (p.Terr > player.Terr) player = p;
                }
    
                return player;
            }
    
            private static Player GetHighestRatedShark(List<Player> sharks)
            {
                Player player = null;
    
                foreach (Player p in sharks)
                {
                    if (player == null) player = p;
    
                    if (p.Shark > player.Shark) player = p;
                }
    
                return player;
            }
    
            private static List<int> GetDraftOrder(List<Player> players, List<Team> teams)
            {
                List<int> draftOrder = new List<int>();
    
                int teamIndex = 0;
                string direction = "r";
    
                // the number of picks matches the number of players
                for (int i = 0; i < players.Count; i++)
                {
                    draftOrder.Add(teamIndex);
    
                    // snake
                    switch (direction)
                    {
                        case "r":
                            {
                                if (teamIndex + 1 == teams.Count)
                                {
                                    direction = "l";
                                }
                                else
                                {
                                    teamIndex++;
                                }
    
                                break;
                            }
    
                        case "l":
                            {
                                if (teamIndex == 0)
                                {
                                    direction = "r";
                                }
                                else
                                {
                                    teamIndex--;
                                }
    
                                break;
                            }
                    }
                }
    
                return draftOrder;
            }
    
            private static List<Player> ShortlistSpiders(List<Player> remaining, int rating)
            {
                List<Player> shortlist = new List<Player>();
    
                foreach (Player player in remaining)
                {
                    if (player.Spid >= rating)
                    {
                        shortlist.Add(player);
                    }
                }
    
                return shortlist.OrderByDescending(p => p.Spid).ToList();
            }
    
            private static List<Player> ShortlistTerrs(List<Player> remaining, int rating)
            {
                List<Player> shortlist = new List<Player>();
    
                foreach (Player player in remaining)
                {
                    if (player.Terr >= rating)
                    {
                        shortlist.Add(player);
                    }
                }
    
                return shortlist.OrderByDescending(p => p.Terr).ToList();
            }
    
            private static List<Player> ShortlistSharks(List<Player> remaining, int rating)
            {
                List<Player> shortlist = new List<Player>();
    
                foreach (Player player in remaining)
                {
                    if (player.Shark >= rating)
                    {
                        shortlist.Add(player);
                    }
                }
    
                return shortlist.OrderByDescending(p => p.Shark).ToList();
            }
    
            private static List<Player> GetPlayersRemaining(List<Player> players, List<Team> teams)
            {
                List<Player> remaining = new List<Player>();
    
                foreach (Player player in players)
                {
                    bool picked = false;
    
                    foreach (Team team in teams)
                    {
                        if (team.Players.Contains(player)) picked = true;
                    }
    
                    if (!picked) remaining.Add(player);
                }
    
                return remaining;
            }
    
            public static List<Team> DraftWithoutCaptain(List<Player> players, List<Team> teams)
            {
                List<int> draftOrder = GetDraftOrder(players, teams);
    
                foreach (int teamIndex in draftOrder)
                {
                    Team currentTeam = teams[teamIndex];
    
                    // see who's left to pick
                    List<Player> remaining = GetPlayersRemaining(players, teams);
    
                    Player player = GetHighestRatedPlayer(remaining);
    
                    currentTeam.AddPlayer(player);
                }
    
                return teams;
            }
    
            private static Player GetHighestRatedPlayer(List<Player> remaining)
            {
                Player player = null;
    
                foreach (Player p in remaining)
                {
                    if (player == null) player = p;
    
                    if (p.Overall > player.Overall) player = p;
                }
    
                return player;
            }
    
            private static Player GetHighestRatedSolidPick(List<Player> remaining)
            {
                Player player = null;
    
                foreach (Player p in remaining)
                {
                    if (player == null) player = p;
    
                    if (p.RatingInContext() > player.RatingInContext()) player = p;
                }
    
                return player;
            }
        }
    }

    Leave a comment:


  • viop11
    replied
    rib u dun need prictice man u haf been vsink this game for 15+ yrs u cud show once/twice a week and b the same

    Leave a comment:


  • Pressure
    replied
    Originally posted by kess View Post
    TSL is a fun league if you manage to get into your head that you will be playing with garbage teams alot of times. Just how it is and improving how it was done in S1 probably isnt easy at all(didnt play s2/3/4).

    WBs and Javs were decent most of time, even if u got the ocasional uneven game. As more games were played, the ratings were more set in stone and it ended up evening the teams as the time went by.
    Regarding basing, it was absolute cancer most of the times and i personally did my bare minimum to qualify for medals/finals. Simply wasnt enjoyable for me, but thats my personal opinion.

    In the end, if you dont take it super serious, its a fun league and a great way to keep the zone active. Id be up for that.
    If the rating systems are tweaked, and bots pick better teams, the current population would provide a better playerbase for a successful TSL than any of the prior seasons, in my opinion.

    Leave a comment:


  • kess
    replied
    TSL is a fun league if you manage to get into your head that you will be playing with garbage teams alot of times. Just how it is and improving how it was done in S1 probably isnt easy at all(didnt play s2/3/4).

    WBs and Javs were decent most of time, even if u got the ocasional uneven game. As more games were played, the ratings were more set in stone and it ended up evening the teams as the time went by.
    Regarding basing, it was absolute cancer most of the times and i personally did my bare minimum to qualify for medals/finals. Simply wasnt enjoyable for me, but thats my personal opinion.

    In the end, if you dont take it super serious, its a fun league and a great way to keep the zone active. Id be up for that.

    Leave a comment:


  • Pressure
    replied
    Originally posted by Rab View Post
    Yeah don't do TSL. It was fine for a while, but ultimately everyone got bored of it, it's just worse than TWDT.
    Even after reading claus' post, I still feel TSL would be perfect for this summer.

    Fun, non-serious, newb-inclusive, noncommittal, and relatively competitive (given current spike in COVID-related activity).

    Leave a comment:


  • Dabram
    replied
    On a personal note I also need a break, I was lucky to be on really good twdt games in back2back seasons, so made a lot of deep playoff runs, then decided to start praccing for twlb after I was convinced to join a very 'serious' contender, which means as euro a lot of night games during my regular workweek (no corona effect for me). So I fully agree with Rab, let's do something a bit more 'chill'. A TSL or twdt league would be perfect for me.

    Leave a comment:


  • Rab
    replied
    Yeah don't do TSL. It was fine for a while, but ultimately everyone got bored of it, it's just worse than TWDT.

    Leave a comment:


  • Dabram
    replied
    Ogron I agree the few tsl games I played felt worse than any twd or ?go base game, which is unfortunate because the concept is genius.but it needed a lot of policing lik you said, which is exactly what you didn't have in mind with an automated league.

    The biggest problem is that you want people to team in TSL, but hardly anyone does because it's 100% about individual stats, which is very frustrating.

    So I was thinking make win ratio count for at least 50% of your rating (maybe even like 75%, we'd have to find the right balance here) other % comes from your individual game stats. Together they make your rank, based on min of X games played, for individual stats counting your top X games maybe, so winning while individually having 1 bad game scorewise isn't a big deal.

    Then because its already based on initial *value (like in twdt), midweek have games with all values together, bot randomizes, for base highest 2 ranked players will be captains and will make balanced lines out of those 14 players, like in ?go base). for weekends with bigger crowds have a high (8>) and low(<8) ranked game. Which makes those weekend games more special and something to look forward to as well.

    To make it less static, by playing well/badly, your *value will in/decrease after X around of games played, so a 7 can become and 8, and 8 drop to a 7. (Especially for dropping you'd need to do really crap to fall down though, to prevent ppl from playing ego style.) Win a lot with good stats in the lower ranks and you'll be playing a level up on Sundays!

    At the end of the season top ranked players perhaps have an all-star final,, and to rank you have to have min X games played..?




    Leave a comment:


  • ogron
    replied
    Originally posted by Cape View Post
    Let me talk to Ogron and Turban to see if they want to help run a TSL league, where we try out new maps/formats.
    I created and ran the exact league you proposed several years ago.



    The first two seasons were decent, then other people took over after I quit and changed the formulas and turned it into a complete joke with awful players high in the ranks killing any credibility the league had beforehand.

    Personally, it was the most unpleasant and toxic thing I've ever been apart of in this game. In TWL and TWDT you have captains who play the best possible lines and if someone quits or is trolling you bench them.

    I ran 5 or 6 seasons of TWDT. Most were pretty successful and half of them were drama free and positive experiences. So it's not like I didn't have a ton of experience running leagues. But TSL was just a toxic monstrosity because of the format, and I can't think of anything I think on less fondly in terms of volunteering in this game.

    In TSL, there are no captains, and as the TSL Head Op you're put in the horrendous position of having to police players.

    TSL ended up creating multiple insane psychos who still stalk and harass me to this day because I ran TSL and gave out warnings and bans (Skyforger, Jessup, etc.) You had players ragequitting games, refusing to play with certain bad players, demanding bans on Jessup because he would just run and extended every game 10 minutes. He would play like 70 jav and 70 wb games which means that he wasted like 140 GP x 10 minutes x 30 or 40 players stuck in spec waiting for the next game equalled:

    One player singlehandedly wasted 840 man hours of our lives running every game per season.

    I took a year off the game after running 2 seasons of TSL, and I swore to never volunteer and run a league ever again, and I have no intention of doing so.

    The concept is really good though, and with the website created for it it can be run pretty easily, especially if you reverted the formulas to the ones I originally put in place, although basing is inarguably the weakest aspect of TSL due to difficulty in matchmaking even teams and quantifying performance in shark, and to a lesser degree spider.

    You could make a legitimate case for removing basing from TSL, and putting something else for base in its place.



    You run a bunch of games, randomize the teams, and the Standings are represented by the total dollar value of your best 20 games.

    The formula is incredibly simple but effective:

    Kills + Plus-Minus + Team Bonus

    Team Bonus Chart:

    50 kills (win) -- $7
    48-49 kills (loss) -- $5
    46-47 kills (loss) -- $4
    44-45 kills (loss) -- $3
    42-43 kills (loss) -- $2
    40-41 kills (loss) -- $1
    0-39 kills (loss) -- $0


    So if you go 25-4 in a win, it's:

    Kills (25) + Plus-Minus (19) + Team Bonus (7) = $51

    If you go 10-10 in a 50-44 loss, it's:

    Kills (10) + Plus-Minus (0) + Team Bonus (3) = $13

    If you go 12-6 in a win, it's:

    Kills (12) + Plus-Minus (6) + Team Bonus (7) = $25

    So if your best 20 games amounted to $400, that was your score in the Standings.

    This did a pretty decent job of letting people play a lot, while also allowing elite players who weren't super active to still make the Top 10. Ease was able to finish #2 in TSLJ despite only playing less than 25 games per season, even against players grinding out 70-80 games.

    I also excluded anyone below $500 from TSLD and TSLJ medals because of reduced activity from veterans in Season 2, where bad players would play 80 games and slowly grind up into the bottom of the Top 10 with like $470ish dollars. If you can't average $25 a game (which is like 12-6 in a win) in 20 games when you play 80 games a season, you don't deserve a medal and didn't perform well.

    One of the reasons I didn't use a player's average dollar amount per game, and only counted the 20 best games, was that player's would get a good average then park their score and retire for the season, reducing activity.

    There would also be some bad matchups produced or people quitting turning some games into a joke, and if every game counts it creates even more raging and toxicity than is already present, in an already toxic format (solo ranking.)

    These standards and policing are what made winning TSL the first two seasons desirable for many players -- being in the Top 10 with over $500 actually meant something. Everything they did afterwards lost them credibility and a lot of veterans didn't return to TSL after I left because it got turned into a joke overrun by bad players who were mad at me because I held the league to a high standard.

    If you want good players to return to TSL, every season after the first two should be completely scrapped and erased from history, and the old formulas and standards should be put in place. As it stands, with the inclusion of Seasons 3/4/5 of TSL I consider the league a total joke and refuse to recognize it.

    I tried to help zone activity, volunteer, and create something everyone could play, but that medals would be something difficult to attain and require talent and performance. If I could go back in time I would never have created TSL and ran it, it was an awful experience overall and the amount of bad players who are complete psychos who harassed me was just beyond the pale, and upper staff's constant meddling and refusal to deal with some of those people soured my relationship pretty badly with them.

    If you think you can navigate that realm and deal with policing players, then go for it.

    If you're planning on altering maps, you should definitely implement your basing map with an expanded cram. The matchup algorithm was fine for WB and Javs but really struggled with basing matchmaking and produced too many uneven games. Those games would be much more tolerable if you spend way more time in Flagroom battles instead of stuck in mid unable to break cram because your team sucks.

    I personally feel like the warbird map should be left alone and is good as-is and that Tiny and Bram's experiment was a flop, but not everyone agrees.

    I liked some of the changes in TWDT-J with the map feature more interesting architectural nodes to fight through and more holes to get fun shots through, so those 2 leagues are definitely ripe for exploration in terms of arena creation.

    My feeling is that TSL is something that should be a rarely run, limited time event and not a constant in the game. There is something primal about TWL and TWDT as team leagues where you're a cohesive unit working towards a common goal that just isn't present in TSL or Elim. They will just never have the same status or prestige as those other two leagues. There's just something much more appealing to us on a deeper level doing stuff as a group, although I'm not going to go into a diatribe about human tribal instincts on a genetic level in relation to team-oriented leagues.

    TSL and Elim leagues, the less you play them, the more interesting and attractive they are. If you used them between TWDT and TWL seasons in limited fasion they could be really fun. Where everyone agrees to play an Elim league for a month, or everyone plays TSL for a month and there are scheduled games.

    But the more you play TSL and Elim seasons, the more people just drift away and stop logging in and get bored. There's something innate where it's just the more of it you do, the worse it gets.

    I'm happy to offer up any insights I have, but I will never agree to be involved in leagues ever again. I'm also strongly considering taking a break for awhile after TWL. Since I came back in November 2018 we've played Basing Cup, TWDT, TWL, TWDT, TWDT, TWDT, Basing Cup, and TWL in a span of 20 months, so I need a break. If you have questions I'd get 'em in before TWL Finals on Sunday, because I might not be online for a bit afterwards.

    Good luck.
    Last edited by ogron; 06-18-2020, 03:40 AM.

    Leave a comment:


  • Cape
    replied
    Let me talk to Ogron and Turban to see if they want to help run a TSL league, where we try out new maps/formats.

    Leave a comment:


  • Pressure
    replied
    Cape, run TSL. I can't commit to a full-time coordinator position, but I can help, as long as people are willing to host and rework the bots to adjust the completely fucked up rating system. As I recall, the rating system had a lot of potential, and resulted in pretty quality overall games and finals, but ultimately there were a lot of issues with the rating system and the bots picking fair teams.

    Let's definitely get TSL started, though. After all, it is summer.

    Leave a comment:


  • Jessup
    replied
    Originally posted by skyforger View Post
    invisijav league
    lol :laugh4:

    Leave a comment:


  • Nipple Nibbler
    replied
    Originally posted by Sulla View Post

    U still prac? Lol
    This is why you're still a 7* shark

    Leave a comment:


  • Sulla
    replied
    Originally posted by Rab View Post
    Something that doesn't require me to stay up to 1am for practice games.
    U still prac? Lol

    Leave a comment:


  • Iron
    replied
    TSL games were during weeks, dont see why not run 2 leagues, TSL + TWDT for example

    Leave a comment:

Working...
X