<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Bevan Philip - Highlights</title><description>Recent highlights from Bevan Philip</description><link>https://bphilip.uk/</link><item><title>Student Loan advertising and perverse incentives</title><link>https://bphilip.uk/blog/2026-02-08-student-loan-advertising-and-perverse-incentives/</link><guid isPermaLink="true">https://bphilip.uk/blog/2026-02-08-student-loan-advertising-and-perverse-incentives/</guid><description>Were a generation of students mislead?</description><pubDate>Sun, 08 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It feels weird to truly understand the terms of your loan nearly a decade after it started, and nearly three years after you started repaying it. Frankly, it feels bad to admit. But that is the case for many of us with the UK Plan 2 Student Loan.&lt;/p&gt;
&lt;p&gt;Of course, the onus was on us. We had the ability to read the Government websites and truly understand the terms, before making the decision. Many of us would have probably made the same decision anyway.&lt;/p&gt;
&lt;p&gt;But students are already overworked. The hardest exams so far are on the horizon. We’ve got to actually apply, and pick our five universities. Some may even be working part-time jobs.&lt;/p&gt;
&lt;p&gt;So, when teachers and trusted adults tell us to effectively ignore the loan, many of us do. &lt;a href=&quot;https://www.theguardian.com/money/2026/feb/06/graduates-student-loans-finances&quot;&gt;So many of us were blind to the true scale of what we were taking on.&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;She was 17 when she first began looking into student finance and 18 when she signed up for it. She says the scale and longevity of the debt was not fully explained. “The way it was explained, it didn’t really capture the long-term nature of it,” she says. “It was underplayed.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;She says the advice from teachers was that the loans would be a tiny percentage of their pay, and it was unlikely they would be repaid in full, with the outstanding balance written off after 30 years.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr/&gt;
&lt;p&gt;I was pretty extensive in my university research. I was trawling through Unistats (now DiscoverUni), to the point where I designed a &lt;a href=&quot;https://github.com/bevan-philip/unistats-cli-browser&quot;&gt;TUI&lt;/a&gt; to extract the data I really wanted from the website, so that I could quickly trawl through the myriad of universities, and the different course permutations that existed.&lt;/p&gt;
&lt;p&gt;Before I’d even started my career, I was already aware of my likely earnings, based on those who had travelled the same path.&lt;/p&gt;
&lt;p&gt;So, despite the fact that I &lt;em&gt;knew&lt;/em&gt; I’d be a high earner, I was still blind to the fact that my interest rate would be doubled once I reached that point. All of my decision making was less about minimizing the loan, but more about maximizing my student experience.&lt;/p&gt;
&lt;p&gt;Looking back, there are a lot of forks in the road, where I made a decision partially based on my naïve understanding of the system. And while, even with the knowledge, I may have made the same decision, I just wish I had the full picture to make it.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Did teachers have perverse incentives to get us to ignore the realities of the loans?&lt;/p&gt;
&lt;p&gt;We’ve already seen this with the English Baccalaureate. Many students, myself included, were driven to this path by false promises from our teachers, that the EBacc would improve our university admission odds. Of course, anyone who has gone through the system now knows this is false - the EBacc does not matter for any good university&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;However, part of this adoption was driven by Government pressures. &lt;a href=&quot;https://www.sec-ed.co.uk/content/news/the-ebacc-effect-teachers-anger-at-narrowing-curriculum&quot;&gt;Teachers&lt;/a&gt; were &lt;a href=&quot;https://www.tes.com/magazine/archived/no-one-wins-race-perverse-incentives&quot;&gt;actively&lt;/a&gt; &lt;a href=&quot;https://teacherhead.com/2015/06/13/ebacc-for-all-shackles-on-or-off/&quot;&gt;pushing&lt;/a&gt; students towards it, because it would lead to &lt;a href=&quot;https://www.bbc.co.uk/news/education-42568038&quot;&gt;higher placements in league tables&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Just as with the EBacc, institutional incentives may have influenced how student loans were presented to us. Sixth forms and colleges must publish “destination data”, which shows the short-term outcomes for students at the institution. Inevitably, this is used as advertising material.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/1.DZ1EjjLa_ZFUPCP.webp&quot; alt=&quot;Image 1&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1002&quot; height=&quot;59&quot;&gt;&lt;/p&gt;
&lt;p&gt;Given the cultural reverence for university attendance by parents &amp;amp; students, they’ll want to boost the statistics here, even when it isn’t the right option.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Similarly, did the various Governments have incentives to push students towards this path? A ridiculously high interest rate, and a long-term commitment, allow the Government to extract a lot of wealth from your high earners, all without it being a tax.&lt;/p&gt;
&lt;p&gt;As we now &lt;a href=&quot;https://blog.moneysavingexpert.com/2026/01/beware-plan-2-student-loan-repayment-freeze/&quot;&gt;watch fiscal drag&lt;/a&gt; being applied to the loan, Governments can grow this base of “high earners”, totally separated from the underlying financial data.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;The obvious fix here is properly communicating the reality of the loan. Producing material that communicates the loan in real terms to financially illiterate teenagers. Having educators truly make students understand the reality of the choice they are taking. The loan is complicated, and only grows in complexity throughout your career: you have to communicate as much of this as early as possible, to give students the best foundation to make informed decisions. Even Martin Lewis knows how difficult it is.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s impossible to do it accurately. There are too many variables and assumptions, both on your career, income and on what will happen to the economy. I know you’ll hate that answer […]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.moneysavingexpert.com/2026/01/beware-plan-2-student-loan-repayment-freeze/#ai:~:text=It%27s%20impossible%20to%20do%20it%20accurately%2E%20There%20are%20too%20many%20variables%20and%20assumptions%2C%20both%20on%20your%20career%2C%20income%20and%20on%20what%20will%20happen%20to%20the%20economy%2E&quot;&gt;Martin Lewis&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But the reality is, will the various parties be interested in this change, while the perverse incentives exist? The loans have only gotten longer: Plan 5 is now 40 years (but without the high earner trap). Demographic change &lt;a href=&quot;https://www.londoncentric.media/p/london-primary-schools-competition-places-amazon-voucher-instagram-adverts&quot;&gt;is only driving schools to more insane methods to gain students&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is heartening to see the campaign against this rising, but those campaigns need to widen their focus to ensure the next generation doesn’t face the same trap as us.&lt;/p&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;Most universities did this via omission, but I distinctly remember Cambridge University actively calling it out as something they did not consider. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded></item><item><title>The tacit feel of a game</title><link>https://bphilip.uk/blog/2026-01-05-the-tacit-feel-of-a-game/</link><guid isPermaLink="true">https://bphilip.uk/blog/2026-01-05-the-tacit-feel-of-a-game/</guid><description>How game developers and players perceive a game differently.</description><pubDate>Mon, 05 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Something feels wrong with Counter-Strike 2. But nobody knows quite what, if anything.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My one wish for next season… for Counter Strike to improve their gameplay and their sub-tick if they want to stick to it
&lt;a href=&quot;https://xcancel.com/BLASTPremier/status/2005587095570772097&quot;&gt;NiKo, CS2 professional&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Game developers have a lot of tacit and explicit knowledge about their titles. They know the systems and the interactions between them, and what results they produce.&lt;/p&gt;
&lt;p&gt;But players of a game have a tacit &lt;em&gt;feel&lt;/em&gt; about the game. They can evaluate the end result of these systems far more accurately than most developers can. In Counter-Strike, most complex movement is out of reach of developers (&lt;a href=&quot;https://www.youtube.com/watch?v=ew0xTcLHeiY&quot;&gt;see this incredible example from ropz&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With the move from CS:GO to CS2, the networking model was overhauled. While the old tick based system runs under the hood, a separate timestamp is networked with each action, to allow for more precise modelling of game events&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. The underlying tick based system has been hardcoded to 64 updates per second.&lt;/p&gt;
&lt;style&gt;.diagram-container {
  margin: 2rem 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.diagram-box {
  border: 2px solid #d1d5db;
  background-color: #f3f4f6;
  border-radius: 0.5rem;
  padding: 0.5rem;
}
@media (prefers-color-scheme: dark) {
  .diagram-box {
    border-color: #6b7280;
    background-color: #374151;
  }
}
.diagram-svg {
  width: 100%;
  max-width: 100%;
  height: auto;
}&lt;/style&gt;
&lt;div class=&quot;diagram-container&quot;&gt;&lt;div class=&quot;diagram-box&quot;&gt;&lt;svg viewBox=&quot;0 0 800 300&quot; class=&quot;diagram-svg text-gray-700 dark:text-gray-300&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;style&gt;.tick-line { stroke: #9CA3AF; }
      .tick-label { fill: #6B7280; }
      .dark .tick-label { fill: #9CA3AF; }
      .event-label { fill: currentColor; }
      .title-text { fill: currentColor; font-weight: bold; }
      .caption-text { fill: #6B7280; }
      .dark .caption-text { fill: #9CA3AF; }&lt;/style&gt;&lt;g id=&quot;csgo-system&quot;&gt;&lt;text x=&quot;400&quot; y=&quot;40&quot; text-anchor=&quot;middle&quot; font-size=&quot;22&quot; class=&quot;title-text&quot;&gt;CS:GO (Tick-Based)&lt;/text&gt;&lt;g id=&quot;csgo-ticks&quot;&gt;&lt;line x1=&quot;120&quot; y1=&quot;80&quot; x2=&quot;120&quot; y2=&quot;220&quot; class=&quot;tick-line&quot; stroke-width=&quot;2.5&quot;&gt;&lt;/line&gt;&lt;text x=&quot;120&quot; y=&quot;65&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; class=&quot;tick-label&quot;&gt;0ms&lt;/text&gt;&lt;line x1=&quot;280&quot; y1=&quot;80&quot; x2=&quot;280&quot; y2=&quot;220&quot; class=&quot;tick-line&quot; stroke-width=&quot;2.5&quot;&gt;&lt;/line&gt;&lt;text x=&quot;280&quot; y=&quot;65&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; class=&quot;tick-label&quot;&gt;15.6ms&lt;/text&gt;&lt;line x1=&quot;440&quot; y1=&quot;80&quot; x2=&quot;440&quot; y2=&quot;220&quot; class=&quot;tick-line&quot; stroke-width=&quot;2.5&quot;&gt;&lt;/line&gt;&lt;text x=&quot;440&quot; y=&quot;65&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; class=&quot;tick-label&quot;&gt;31.3ms&lt;/text&gt;&lt;line x1=&quot;600&quot; y1=&quot;80&quot; x2=&quot;600&quot; y2=&quot;220&quot; class=&quot;tick-line&quot; stroke-width=&quot;2.5&quot;&gt;&lt;/line&gt;&lt;text x=&quot;600&quot; y=&quot;65&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; class=&quot;tick-label&quot;&gt;46.9ms&lt;/text&gt;&lt;/g&gt;&lt;g id=&quot;csgo-events&quot;&gt;&lt;circle cx=&quot;120&quot; cy=&quot;150&quot; r=&quot;7&quot; fill=&quot;#10B981&quot;&gt;&lt;/circle&gt;&lt;text x=&quot;120&quot; y=&quot;120&quot; text-anchor=&quot;middle&quot; font-size=&quot;15&quot; class=&quot;event-label&quot;&gt;Move&lt;/text&gt;&lt;circle cx=&quot;220&quot; cy=&quot;150&quot; r=&quot;7&quot; fill=&quot;#EF4444&quot; opacity=&quot;0.6&quot;&gt;&lt;/circle&gt;&lt;text x=&quot;220&quot; y=&quot;195&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; class=&quot;tick-label&quot;&gt;12ms&lt;/text&gt;&lt;line x1=&quot;227&quot; y1=&quot;150&quot; x2=&quot;273&quot; y2=&quot;150&quot; stroke=&quot;#EF4444&quot; stroke-width=&quot;2&quot; stroke-dasharray=&quot;5,4&quot; opacity=&quot;0.7&quot;&gt;&lt;/line&gt;&lt;polygon points=&quot;273,150 265,154 265,146&quot; fill=&quot;#EF4444&quot; opacity=&quot;0.7&quot;&gt;&lt;/polygon&gt;&lt;circle cx=&quot;280&quot; cy=&quot;150&quot; r=&quot;7&quot; fill=&quot;#EF4444&quot;&gt;&lt;/circle&gt;&lt;text x=&quot;280&quot; y=&quot;120&quot; text-anchor=&quot;middle&quot; font-size=&quot;15&quot; class=&quot;event-label&quot;&gt;Shot&lt;/text&gt;&lt;circle cx=&quot;380&quot; cy=&quot;150&quot; r=&quot;7&quot; fill=&quot;#3B82F6&quot; opacity=&quot;0.6&quot;&gt;&lt;/circle&gt;&lt;text x=&quot;380&quot; y=&quot;195&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; class=&quot;tick-label&quot;&gt;28ms&lt;/text&gt;&lt;line x1=&quot;387&quot; y1=&quot;150&quot; x2=&quot;433&quot; y2=&quot;150&quot; stroke=&quot;#3B82F6&quot; stroke-width=&quot;2&quot; stroke-dasharray=&quot;5,4&quot; opacity=&quot;0.7&quot;&gt;&lt;/line&gt;&lt;polygon points=&quot;433,150 425,154 425,146&quot; fill=&quot;#3B82F6&quot; opacity=&quot;0.7&quot;&gt;&lt;/polygon&gt;&lt;circle cx=&quot;440&quot; cy=&quot;150&quot; r=&quot;7&quot; fill=&quot;#3B82F6&quot;&gt;&lt;/circle&gt;&lt;text x=&quot;440&quot; y=&quot;120&quot; text-anchor=&quot;middle&quot; font-size=&quot;15&quot; class=&quot;event-label&quot;&gt;Jump&lt;/text&gt;&lt;/g&gt;&lt;text x=&quot;400&quot; y=&quot;260&quot; text-anchor=&quot;middle&quot; font-size=&quot;15&quot; class=&quot;caption-text&quot;&gt;Events snapped to nearest tick boundary&lt;/text&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/div&gt;&lt;div class=&quot;diagram-box&quot;&gt;&lt;svg viewBox=&quot;0 0 800 280&quot; class=&quot;diagram-svg text-gray-700 dark:text-gray-300&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;style&gt;.tick-line { stroke: #9CA3AF; }
      .tick-label { fill: #6B7280; }
      .dark .tick-label { fill: #9CA3AF; }
      .event-label { fill: currentColor; }
      .title-text { fill: currentColor; font-weight: bold; }
      .caption-text { fill: #6B7280; }
      .dark .caption-text { fill: #9CA3AF; }&lt;/style&gt;&lt;g id=&quot;cs2-system&quot;&gt;&lt;text x=&quot;400&quot; y=&quot;40&quot; text-anchor=&quot;middle&quot; font-size=&quot;22&quot; class=&quot;title-text&quot;&gt;CS2 (Sub-Tick)&lt;/text&gt;&lt;g id=&quot;cs2-ticks&quot;&gt;&lt;line x1=&quot;120&quot; y1=&quot;80&quot; x2=&quot;120&quot; y2=&quot;200&quot; class=&quot;tick-line&quot; stroke-width=&quot;2.5&quot;&gt;&lt;/line&gt;&lt;text x=&quot;120&quot; y=&quot;65&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; class=&quot;tick-label&quot;&gt;0ms&lt;/text&gt;&lt;line x1=&quot;280&quot; y1=&quot;80&quot; x2=&quot;280&quot; y2=&quot;200&quot; class=&quot;tick-line&quot; stroke-width=&quot;2.5&quot;&gt;&lt;/line&gt;&lt;text x=&quot;280&quot; y=&quot;65&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; class=&quot;tick-label&quot;&gt;15.6ms&lt;/text&gt;&lt;line x1=&quot;440&quot; y1=&quot;80&quot; x2=&quot;440&quot; y2=&quot;200&quot; class=&quot;tick-line&quot; stroke-width=&quot;2.5&quot;&gt;&lt;/line&gt;&lt;text x=&quot;440&quot; y=&quot;65&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; class=&quot;tick-label&quot;&gt;31.3ms&lt;/text&gt;&lt;line x1=&quot;600&quot; y1=&quot;80&quot; x2=&quot;600&quot; y2=&quot;200&quot; class=&quot;tick-line&quot; stroke-width=&quot;2.5&quot;&gt;&lt;/line&gt;&lt;text x=&quot;600&quot; y=&quot;65&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; class=&quot;tick-label&quot;&gt;46.9ms&lt;/text&gt;&lt;/g&gt;&lt;g id=&quot;cs2-events&quot;&gt;&lt;circle cx=&quot;120&quot; cy=&quot;140&quot; r=&quot;7&quot; fill=&quot;#10B981&quot;&gt;&lt;/circle&gt;&lt;text x=&quot;120&quot; y=&quot;115&quot; text-anchor=&quot;middle&quot; font-size=&quot;15&quot; class=&quot;event-label&quot;&gt;Move&lt;/text&gt;&lt;text x=&quot;120&quot; y=&quot;170&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#10B981&quot;&gt;0.0ms&lt;/text&gt;&lt;circle cx=&quot;220&quot; cy=&quot;140&quot; r=&quot;7&quot; fill=&quot;#EF4444&quot;&gt;&lt;/circle&gt;&lt;text x=&quot;220&quot; y=&quot;115&quot; text-anchor=&quot;middle&quot; font-size=&quot;15&quot; class=&quot;event-label&quot;&gt;Shot&lt;/text&gt;&lt;text x=&quot;220&quot; y=&quot;170&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#EF4444&quot;&gt;12.0ms&lt;/text&gt;&lt;circle cx=&quot;380&quot; cy=&quot;140&quot; r=&quot;7&quot; fill=&quot;#3B82F6&quot;&gt;&lt;/circle&gt;&lt;text x=&quot;380&quot; y=&quot;115&quot; text-anchor=&quot;middle&quot; font-size=&quot;15&quot; class=&quot;event-label&quot;&gt;Jump&lt;/text&gt;&lt;text x=&quot;380&quot; y=&quot;170&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;#3B82F6&quot;&gt;28.0ms&lt;/text&gt;&lt;/g&gt;&lt;text x=&quot;400&quot; y=&quot;240&quot; text-anchor=&quot;middle&quot; font-size=&quot;15&quot; class=&quot;caption-text&quot;&gt;Events occur at precise sub-tick timestamps&lt;/text&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/div&gt;&lt;p class=&quot;text-center text-sm text-gray-600 dark:text-gray-400 mt-2 italic&quot;&gt;Comparison of networking systems: CS:GO forces events to tick boundaries, while CS2 preserves precise timing&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;One assumption that immediately wrong from the developer side, was that sub-tick would rectify differences in grenade trajectories across tick rates (grenade throws involving jumping behave different from 64-tick to 128-tick). This did not prove to be the case, and was “resolved” by hard-coding the tick rate.&lt;/p&gt;
&lt;p&gt;But beyond all of this, players have continually complained about the game feeling “off”. This is a vague feeling, that is difficult to appreciate. And indeed, the first thing that comes to mind is an anecdote from Minh Le, where he describes &lt;a href=&quot;https://youtu.be/-yDM9XRK2lU?t=500&quot;&gt;artificially lowering the ping&lt;/a&gt; on the scoreboard to make the game appear more responsive, which tricked people.&lt;/p&gt;
&lt;p&gt;However, saying that players cannot identify minute differences through game play alone is not accurate. In an experiment, &lt;a href=&quot;https://www.youtube.com/watch?v=6f5fEgSRAKg&quot;&gt;professional player ropz&lt;/a&gt; was able to accurately identify the tick rate of the server he was playing on through aim and movement.&lt;/p&gt;
&lt;p&gt;When a large group of them say something is wrong… there is something worth exploring. I’m reminded of the anecdote of &lt;a href=&quot;https://youtu.be/0zqeTYuXUig?t=149&quot;&gt;Jim Clark&lt;/a&gt; noticing that a single wheel bearing was starting to wear while driving, which was not noticeable without completely disassembling the car&lt;/p&gt;
&lt;p&gt;The problem is: how do you test for this? A “feeling” is not empirical evidence. Even &lt;a href=&quot;https://www.reddit.com/r/GlobalOffensive/comments/1blc8ks/when_will_crouchjumping_be_fixed/kw4flqo/&quot;&gt;inconsistent bugs&lt;/a&gt; can be difficult for developers to reproduce&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, if they don’t have the requisite understanding of the game mechanic.&lt;/p&gt;
&lt;p&gt;Developers don’t need to be hyper-skilled to produce great games. Personally, the game &lt;em&gt;design&lt;/em&gt; of Counter-Strike continues to be fantastic, despite the developers not being outrageously skilled. However, Counter-Strike is predicated on being a simplistic&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; game, where players advantage themselves through precise gameplay. For a game like this, solving this gap is crucial to providing the best experience for players.&lt;/p&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;This is an oversimplification of the network model. But it is good enough to understand the base premise. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;This bug was not the most difficult to replicate: even I, a relatively middle of the road player, could do so frequently enough. This demonstrates how different the experience for a developer can be. This would cause furore a day later, when a &lt;a href=&quot;https://www.youtube.com/clip/UgkxKyBDq-2LKYp2LIsbiUHcJAcn3lD3q8Ujj&quot;&gt;player lost a round&lt;/a&gt; in the on-going Valve sponsored event, because of this bug. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;In contrast to the closest competitor VALORANT, where agent abilities can dictate a round. &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded></item><item><title>Exploring the tragedy of the Counter-Strike 2 server browser</title><link>https://bphilip.uk/blog/2025-08-25-the-cs2-server-browser-where-community-goes-to-die/</link><guid isPermaLink="true">https://bphilip.uk/blog/2025-08-25-the-cs2-server-browser-where-community-goes-to-die/</guid><description>An examination of the mess that is the CS2 server browser.</description><pubDate>Mon, 25 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For those who enjoy Counter-Strike community servers, the situation in Counter-Strike 2 is rather dire.&lt;/p&gt;
&lt;p&gt;An avalanche of spam has rendered the server browser unusable. The transition from Global Offensive killed multiple small communities. And large server providers have taken advantage of these problems to monopolise the market.&lt;/p&gt;
&lt;p&gt;Trying to find a server either involves capitulating to these big vendors, or trawling through a trench of spam.&lt;/p&gt;
&lt;p&gt;Scraping the server browser allows us to have some insight into the state of the market.&lt;/p&gt;
&lt;h2 id=&quot;getting-the-servers&quot;&gt;Getting the servers&lt;/h2&gt;
&lt;p&gt;The first task was extracting servers from Valve’s master list.&lt;/p&gt;
&lt;p&gt;This is not a trivial matter: Valve provide a REST endpoint for doing so, but the endpoint is restricted to ~10-50k results per query, and does not provide any pagination support. This is because the data is extremely volatile, changing on every single query.&lt;/p&gt;
&lt;p&gt;You can provide query parameters to change what servers are returned. By performing multiple segmented queries (i.e. by polling for maps individually, querying by different regions), and polling over a long period of time, we can gather a lot more servers. We store the maximum player count, so that we can get a feel for how occupied a server is.&lt;/p&gt;
&lt;p&gt;The best way to approach this technique would have been to replicate Steam’s server browser. However, this would still require segmentation (due to the volume of servers), and has a messier authentication story.&lt;/p&gt;
&lt;p&gt;After pulling this data, I threw it into a DuckDB database to analyse.&lt;/p&gt;
&lt;h2 id=&quot;the-spam-problem&quot;&gt;The spam problem&lt;/h2&gt;
&lt;p&gt;Across an hour period with ~1.1m active players, we pulled ~92,000 community servers with ~500,000 players. We pulled ~144,000 Valve servers, with ~910,000 players.&lt;/p&gt;
&lt;p&gt;There is already a problem here: there are nearly 400,000 unexpected players.&lt;/p&gt;
&lt;p&gt;Our method of sampling does have double-counting issues: if a player moves servers, they will be counted twice in the data set.&lt;/p&gt;
&lt;p&gt;However, another issue is causing us trouble: fake servers. These are servers that report high player counts, but in reality, they have no players at all.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/2.ZJJh2Wml_Zv1nj5.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2555&quot; height=&quot;1200&quot;&gt;
For a regular user, this is the experience of trying to find a community server.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Counter-Strike is usually a 5v5 game, but community servers can go up to 32 players. If we remove all servers above 32 players from our data set, we remove 200,000 players from our data set.&lt;/p&gt;
&lt;p&gt;This still only captures a portion of the spam:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/1.DjXU7vst_Z12KK8M.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1388&quot; height=&quot;332&quot;&gt;
This query eliminates many legitimate servers, but we can still find spam here.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Beyond fake servers, another form of spam is simply having a lot of real servers occupy the server list.&lt;/p&gt;
&lt;p&gt;Here are a sample of servers that are spam, either by being fake, or by suffocating the list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1290 servers with the name &lt;code&gt;&amp;#39;Registre-se e jogue @ gamersclub.com.br&amp;#39;&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;These are legitimate but inaccessible servers for the third party matchmaking service GamersClub. Ideally, these would not be visible on the server list.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;650 servers with the name &lt;code&gt;MIRAGE | ЧИЛОВЫЙ СЕРВЕР #3&lt;/code&gt;, and another 650 servers with the name &lt;code&gt;MIRAGE | ЧИЛОВЫЙ СЕРВЕР #1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;~2000 servers with the prefix &lt;code&gt;stalnoy&lt;/code&gt;, with a total of 0 players.&lt;/li&gt;
&lt;li&gt;Servers with the name &lt;code&gt;GPT*&lt;/code&gt; had a combined total of 1238 players across 18 servers, for an average of 69 players per server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-and-why&quot;&gt;How, and why?&lt;/h2&gt;
&lt;p&gt;Valve requires game servers to be registered, using Game Server Login Tokens (GSLTs). These are associated with your Steam ID, and require you to have an account that owns the game and is in good standing.&lt;/p&gt;
&lt;p&gt;But this system has been largely evaded. For one, this system requires enforcement from Valve to provide any meaningful results. The other big problem is that spammers have access to a lot of Counter-Strike accounts. Sites offer Counter-Strike 2 accounts for sale for less than a £1.&lt;/p&gt;
&lt;p&gt;The main reason people engage in spam is advertisement. If players can only see your server… they might try it out. While the servers may be fake, they can proxy you to real servers, albeit without the player numbers that were advertised.&lt;/p&gt;
&lt;h2 id=&quot;the-big-fish&quot;&gt;The big fish&lt;/h2&gt;
&lt;p&gt;Amongst the spam, a significant portion of the market has been captured by large providers.&lt;/p&gt;
&lt;p&gt;To identify server providers, the server name was broken down per word (and cleaned up), common words (like “mirage”) were removed, and then for each word, a cumulative total of various statistics was gathered.&lt;/p&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align:right&quot;&gt;Rank&lt;/th&gt;&lt;th style=&quot;text-align:left&quot;&gt;Keyword&lt;/th&gt;&lt;th style=&quot;text-align:left&quot;&gt;Total Players&lt;/th&gt;&lt;th style=&quot;text-align:right&quot;&gt;Server Count&lt;/th&gt;&lt;th style=&quot;text-align:right&quot;&gt;Avg Players per Server&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;fb-csru&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;58,755&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;1654&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;35.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;cybershokenet&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;15,233&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;2177&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;3&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;napas&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;13,528&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;303&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;44.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;4&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;csbullnet&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;8,615&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;239&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;36&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;5&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;cybersm9s&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;6,033&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;159&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;37.9&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;From the get-go, we can spot some problems. If the average number of players per server is above ~30, the likelihood of it being spam is high.&lt;/p&gt;
&lt;p&gt;“fb-cs.ru” report ~300 active players on their own website, a vast discrepancy from what we see in the server browser. That is nearly 58,000 fake players within our data set.&lt;/p&gt;
&lt;p&gt;When removing all servers over 32 players, you get this slightly better, but still filled with fakes list. Nevertheless, it gives a good idea as to the lay of the land.&lt;/p&gt;










































































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align:right&quot;&gt;Rank&lt;/th&gt;&lt;th style=&quot;text-align:left&quot;&gt;Keyword&lt;/th&gt;&lt;th style=&quot;text-align:left&quot;&gt;Total Players&lt;/th&gt;&lt;th style=&quot;text-align:right&quot;&gt;Server Count&lt;/th&gt;&lt;th style=&quot;text-align:right&quot;&gt;Avg Players per Server&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;cybershokenet&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;15,162&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;2175&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;fb-csru&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;11,354&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;862&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;13.2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;3&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;napas&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;4,349&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;153&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;28.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;4&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;legcs2ru&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;4,335&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;4144&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;5&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;xplaygg&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;3,462&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;905&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;3.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;6&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;tverpubspace&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;2,729&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;172&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;15.9&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;7&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;r0对战平台天梯服务器&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;2,097&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;500&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;4.2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;8&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;csbullnet&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;1,678&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;129&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;13&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;9&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;r0对战平台天梯服&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;1,616&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;164&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;9.9&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;10&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;fastcupnet&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;1,549&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;328&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;4.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;11&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;cybersm9s&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;1,298&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;67&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;19.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;12&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;m9snoi&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;1,128&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;73&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;15.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;13&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;discordggcolateam&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;1,010&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;42&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;24&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;14&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;pracccom&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;961&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;457&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;2.1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;15&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;hollycs&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;919&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;45&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;20.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;16&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;refraggg&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;908&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;937&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;17&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;gamersclubcombr&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;863&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;1293&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;0.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;text-align:right&quot;&gt;18&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;registre-se&lt;/td&gt;&lt;td style=&quot;text-align:left&quot;&gt;857&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;1292&lt;/td&gt;&lt;td style=&quot;text-align:right&quot;&gt;0.7&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;CYBERSHOKE is the primary English speaking provider, and dwarf their competition in xplay.gg.&lt;/p&gt;
&lt;p&gt;Whereas server providers &lt;em&gt;used&lt;/em&gt; to target a small smattering of game modes, they have a smorgasbord of options:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/3.BmibdmJc_ZfRSj9.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2047&quot; height=&quot;979&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;spam-benefits-these-big-providers&quot;&gt;Spam benefits these big providers&lt;/h2&gt;
&lt;p&gt;These big providers have every single popular game mode, a large user base, and an attractive website with all of their servers. As the server browser becomes less and less useful, users will gravitate towards one-stop shops.&lt;/p&gt;
&lt;p&gt;While server groups have existed before, this is a whole new level in size and scope.&lt;/p&gt;
&lt;p&gt;When you become this big, you no longer need to rely on volunteer work to maintain servers: you can hire full-time developers and administrators.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/4.CxxHDG-5_Z2ieb17.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1929&quot; height=&quot;664&quot;&gt;
A translated screenshot of an &lt;a href=&quot;https://hlmod.net/threads/cs2-poisk-c-razrabotchika-cybershoke.67551/&quot;&gt;advert from Cybershoke&lt;/a&gt;, searching for a C++ developer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/5.DDGH6TdD_ZQ014e.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1324&quot; height=&quot;264&quot;&gt;
Job vacancy for a marketing employee on a &lt;a href=&quot;https://hh.ru/vacancy/89899410&quot;&gt;Russian job board&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;small-providers-will-have-a-harder-time&quot;&gt;Small providers will have a harder time&lt;/h2&gt;
&lt;p&gt;If you invented a novel game mode, you had a first movers advantage. But if you are a small provider, this is no longer the case.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Advertising your game mode is harder, because the server list is broken, and the market is top heavy,&lt;/li&gt;
&lt;li&gt;If your game mode proves successful, the top servers will have it cloned quickly, because they have the developers to do so,&lt;/li&gt;
&lt;li&gt;As a smaller provider, you will be outdeveloped because the bigger providers have the resources,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The CS:GO to CS2 transition is a large part of the problem. Previously, these game modes and server communities developed naturally, leading to many small minnows.&lt;/p&gt;
&lt;p&gt;But as the transition required a total re-write, these big providers could quickly establish first movers’ advantage by hiring full-time employees to replicate all the game modes before everyone else could.&lt;/p&gt;
&lt;p&gt;I was personally fond of a group called XGC, who had these wonderful execute servers (from what I understand, they mostly pioneered the format). The transition to CS2 killed them: first because they struggled to port over the game mode, and then they were outcompeted by these mega groups.&lt;/p&gt;
&lt;p&gt;The two groups offering executes now are CYBERSHOKE and hjemezez. hjemezez operates similarly to CYBERSHOKE.&lt;/p&gt;
&lt;h2 id=&quot;alternative-server-browsers&quot;&gt;Alternative server browsers&lt;/h2&gt;
&lt;p&gt;In the wake of the spam, people began creating their own wrappers around the server browser.&lt;/p&gt;
&lt;p&gt;One prominent one was &lt;code&gt;cs2browser.com&lt;/code&gt;. After a period of unusable server browsers, this offered hope that the community could work around the lack of moderation. Alas, good things don’t last, and they were acquired and integrated by a gambling provider.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In Clash news, We have purchased &lt;code&gt;cs2browser.com&lt;/code&gt;, we will be adding this tool to stash and make it the largest map/server database for all of CS2. More big updates coming to Clash, RustClash and CasesGG soon!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://x.com/HobbesHD/status/1941999298104680624&quot;&gt;Twitter&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/2315530/Saido&quot;&gt;Saido&lt;/a&gt; was a competitor launched around the same time, but never gained any traction and now lays dead.&lt;/p&gt;
&lt;p&gt;From what I can see, &lt;a href=&quot;https://cs2serverlist.com/&quot;&gt;CS2ServerList&lt;/a&gt; and &lt;a href=&quot;https://cs2browser.net&quot;&gt;CS2Browser.net&lt;/a&gt; serve as viable replacement projects.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/smltr/findservers&quot;&gt;FindServers&lt;/a&gt; is a niche project trying to replicate the look and feel of the Source 1 server browser. That being said, having used their code as a reference for this project, I suspect they’re only pulling 30% of the available servers.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;When people yearn for the days of community servers, this is not what they’re expecting to see. Small groups, with admins so readily available, they could be your friends.&lt;/p&gt;
&lt;p&gt;The biggest names in the space aren’t communities. They’re faceless corporations.&lt;/p&gt;
&lt;p&gt;For communities to grow, the environment has to be acceptable to it. The old environment, with a usable server browser, keeping the costs of advertisement low, no longer exists. To compete in this space, you have to reach your users somehow, and the big providers have all of the weapons to pummel you before you even start.&lt;/p&gt;
&lt;p&gt;Evidently, Valve should do something, at least about the spam. But they’ve been asleep at the wheel for years now.&lt;/p&gt;
&lt;p&gt;This should be a warning sign to any game wanting to have community servers. This is not a feature you leave running in the background. It requires maintenance. When your game becomes big, bad actors will emerge into your space.&lt;/p&gt;
&lt;p&gt;Leave it too long, and community servers cease to be a community at all.&lt;/p&gt;
&lt;h2 id=&quot;post-script&quot;&gt;Post-script&lt;/h2&gt;
&lt;h3 id=&quot;skin-changers-ws&quot;&gt;Skin changers: &lt;code&gt;!ws&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;!ws&lt;/code&gt; is a command that allows players to change the skins on their guns. This was a standard plugin for many years, until Valve banned it in &lt;a href=&quot;https://blog.counter-strike.net/server_guidelines/&quot;&gt;2015&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, looking at the server list, you wouldn’t realise this. CYBERSHOKE actively advertises it as a feature of their Premium subscription.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/8.DDjdweab_ZWCQTf.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;764&quot; height=&quot;605&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Valve never actually enforced this in any meaningful way. Outside of a wave of bans in 2015 and 2016, this has mostly been ignored.&lt;/p&gt;
&lt;h3 id=&quot;economics&quot;&gt;Economics&lt;/h3&gt;
&lt;p&gt;Historically, server networks were paid for in the following ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The generosity of the owners,&lt;/li&gt;
&lt;li&gt;Advertising, either via the Message of the Day, or chat messages,&lt;/li&gt;
&lt;li&gt;A small group of generous donators.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/6.DYjcyll7_Z2jhIJK.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
An example of a MOTD loading a HTML page. &lt;a href=&quot;https://forums.alliedmods.net/showthread.php?t=218135&quot;&gt;Pinion&lt;/a&gt; was an infamous group for using this vector to serve adverts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the modern meta, big server networks have “premium” subscriptions, and have advertising from gambling providers directly in-game.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/7._qvfT8-F_Z1OG5p4.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;592&quot; height=&quot;188&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title>Syncing bank transactions to my budget, and experimenting with Cursor</title><link>https://bphilip.uk/blog/2025-03-09-chase-bank-sync/</link><guid isPermaLink="true">https://bphilip.uk/blog/2025-03-09-chase-bank-sync/</guid><description>Some personal learnings from trying vibe coding.</description><pubDate>Sun, 09 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;YNAB is my budgeting tool of choice. It works, and I don’t want the hassle of maintaining my own instance of &lt;a href=&quot;https://actualbudget.org/&quot;&gt;Actual Budget&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;YNAB has support for Open Banking sync, which I do use. However, their API vendor, TrueLayer, continues to lack Chase UK Open Banking support, despite it being available for ~1 year now. Other tools, like Moneyhub, have supported it for yonks now.&lt;/p&gt;
&lt;p&gt;Using the direct bank API yourself is impossible (regulatory requirements), but you can use a intermediary vendor. GoCardless is particularly cool because they offer free access (albeit limited), something with Actual Budget uses for their &lt;a href=&quot;https://actualbudget.org/docs/advanced/bank-sync/gocardless/&quot;&gt;sync implementation&lt;/a&gt;. It should be easy to replicate this for YNAB.&lt;/p&gt;
&lt;p&gt;With some spare time, and a desire to dig into agentic LLM tools, I decided to give it a shot. I’m &lt;a href=&quot;https://github.com/bevan-philip/ynab-gocardless-sync&quot;&gt;pretty happy with the outcome&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;desires&quot;&gt;Desires&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I didn’t want to pay anything additional (I’m trying to budget here…),&lt;/li&gt;
&lt;li&gt;I wanted the tool to be local-only: that way, I only have to trust GoCardless &amp;amp; YNAB.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This ruled out the already existing GoCardless-based tool, &lt;a href=&quot;https://synci.io/&quot;&gt;Synci&lt;/a&gt;. I’m sure it absolutely works great, has a bunch of features my tool will never have, and is risk-free. But better to be safe than sorry.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Doesn’t need to be particularly user-friendly. While I made the best attempt to make it user friendly (as much as a CLI tool can be), the only person it has to be work for is me. Anyone else is a bonus :).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;thoughts-while-building-this&quot;&gt;Thoughts while building this,&lt;/h2&gt;
&lt;p&gt;This project was built a lot on &lt;a href=&quot;https://simonwillison.net/2025/Feb/6/andrej-karpathy/&quot;&gt;vibe coding&lt;/a&gt;. It was a fun experiment, and after some effort, absolutely got me where I wanted to. On the way, I learned a bunch of stuff.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;At work, I’m currently using Roo Code (primarily because our only AI tech is access to a Claude API key). Roo is pretty good, and absolutely does the job.&lt;/li&gt;
&lt;li&gt;But man, Cursor is awesome. The UI is beautiful, and the agentic implementation seems to be just a bit better than Roo. It has the extra layer of polish. Genuinely tempted to shell out for Pro whenever I work on a new project (without Cursor, I’m just manually shelling out for Claude tokens).
&lt;ul&gt;
&lt;li&gt;Oh, and the completions are actually really good.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AI can do a lot of the scaffolding right.&lt;/li&gt;
&lt;li&gt;When the conversation becomes too long, it completely fails to do anything novel or interesting. &lt;a href=&quot;https://youtu.be/EWvNQjAaOHw?t=1024&quot;&gt;Kaparthy’s recent video on LLMs comes with a great explainer&lt;/a&gt; for this behaviour.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.cursor.com/context/rules-for-ai&quot;&gt;Cursor rules&lt;/a&gt; are great in theory, but I couldn’t get it to click.
&lt;ul&gt;
&lt;li&gt;For instance, I asked it to &lt;em&gt;never&lt;/em&gt; suggest installing something, and yet it continued to do so.&lt;/li&gt;
&lt;li&gt;I asked it to use uv to do package management and program invoking. It sometimes did.
&lt;ul&gt;
&lt;li&gt;&lt;img src=&quot;/_astro/uv-rule.BYdAxgvk_Z1BqAbg.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;390&quot; height=&quot;540&quot;&gt;&lt;/li&gt;
&lt;li&gt;I’m not pretending my instructions are even good, but argh, this is frustrating.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;For a bit, I went purely YOLO, and let it go purely agentic… this had some bad results,
&lt;ul&gt;
&lt;li&gt;It installed a bunch of crap to my system pip in a vain attempt to get packages right.&lt;/li&gt;
&lt;li&gt;(The issue here was a bad Python version: 3.8 was too old for some of the packages, and 3.13 was too bleeding edge for many to have distributions: on 3.13, there is no numpy version so it kept trying to compile it, which is a recipe for disaster on Windows).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Interesting quirks,
&lt;ul&gt;
&lt;li&gt;It sometimes get stuck in using older tech.
&lt;ul&gt;
&lt;li&gt;For instance, when it, out of its own volition, implemented a progress bar, it decided to use &lt;code&gt;tqdm&lt;/code&gt; instead of &lt;code&gt;rich&lt;/code&gt; (which was already added to the project).&lt;/li&gt;
&lt;li&gt;And practically everytime it wanted to get the current date, it used &lt;code&gt;utcnow()&lt;/code&gt;, instead of &lt;code&gt;now(datetime.UTC)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The initial plan suggested &lt;code&gt;requests&lt;/code&gt;. Nothing wrong with &lt;code&gt;requests&lt;/code&gt;, but I find &lt;code&gt;httpx&lt;/code&gt; a much better choice.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;It could not resolve an issue where a particular bank account would randomly bomb out: the underlying source being the default &lt;code&gt;httpx&lt;/code&gt; timeout of 5 seconds.&lt;/li&gt;
&lt;li&gt;It used &lt;code&gt;httpx&lt;/code&gt; clients… but insisted on creating one for every request. That’s basically pointless.&lt;/li&gt;
&lt;li&gt;The tool used &lt;code&gt;asyncio&lt;/code&gt; for the implementation. Nothing wrong with that, but wholly unnecessary for a project only performing one REST request at a time (I suspect &lt;code&gt;httpx&lt;/code&gt; is linked quite heavily with &lt;code&gt;asyncio&lt;/code&gt;, so it felt like it &lt;em&gt;had&lt;/em&gt; to use it).&lt;/li&gt;
&lt;li&gt;Disappointed it never attempted to use &lt;a href=&quot;https://docs.python.org/3/library/dataclasses.html&quot;&gt;dataclasses&lt;/a&gt;, until I prompted it to do so.&lt;/li&gt;
&lt;li&gt;For some reason, it hallucinated that the YNAB API did not accept negative numbers (it does, and &lt;em&gt;you need to use negative numbers&lt;/em&gt; for outflow). I suspect this is because YNAB doesn’t support negative numbers, but that’s because it forces you to use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Double-entry_bookkeeping&quot;&gt;double-entry bookkeeping&lt;/a&gt; style in the UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GoCardless’ API limits made debugging issues a pain.. but equally, I should have intervened with my own abilities far earlier. One of the problems of vibe coding is that it is very easy to forget your own cognitive ability. I find I have this problem less at work, likely because I use it less &amp;amp; have to intervene way more often. &lt;a href=&quot;https://simonwillison.net/2025/Mar/6/vibe-coding/&quot;&gt;Simon Willison’s recent take&lt;/a&gt; roughly aligns with what I’m thinking.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;xkcd-1205&quot;&gt;&lt;a href=&quot;https://xkcd.com/1205/&quot;&gt;xkcd #1205&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Historically, this sort of project I wouldn’t have looked at due to the unlikely nature I’d save any time here. As much as it seemed cool, I had other projects I wanted to prioritise.&lt;/p&gt;
&lt;p&gt;But LLMs change the dynamics a lot: it takes substantially less time to get you almost there.&lt;/p&gt;
&lt;p&gt;That being said, you’ve still got to read everything it outputs, build up that mental model, and get stuck in if is unable to deliver the proper solution, which, even in a relatively simple like this one, I find it does shockingly often.&lt;/p&gt;
&lt;p&gt;Either way, I’ll be exploring more ideas that come to me with this tech, and I think that’s a really neat outcome.&lt;/p&gt;</content:encoded></item><item><title>Will Counter-Strike coaching evolve?</title><link>https://bphilip.uk/blog/2024-07-14-will-cs-coaching-evolve/</link><guid isPermaLink="true">https://bphilip.uk/blog/2024-07-14-will-cs-coaching-evolve/</guid><description>Thinking about how aim coaching might be a stepping stone to more advanced coaching</description><pubDate>Sun, 14 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, CS professionals STYKO and EliGE have shared the fact that they have employed the services of aim coaches. Such moves are relatively new to Counter-Strike: while aiming is considered an important aspect to Counter-Strike, professionals usually improve their skill in this venture with deathmatching, or training with Counter-Strike maps such as “aim_botz”, or full bespoke suites such as Refrag (EliGE partly owns Refrag, after acquiring it from ESEA).&lt;/p&gt;
&lt;p&gt;CS, as is typical, is late to the party. VALORANT and Overwatch have diverse aim coaching scenes, and professionals have been already engaging the services of professionals.&lt;/p&gt;
&lt;p&gt;But aiming is just one of many potential areas of the game where an external observer might be useful.&lt;/p&gt;
&lt;h2 id=&quot;lets-take-a-look-at-traditional-sports&quot;&gt;Let’s take a look at traditional sports&lt;/h2&gt;
&lt;p&gt;Shooting coaches are present in both football, basketball, and hockey, even if the meaning of shooting differs. Football also has coaches for each of the positions on the pitch, such as a defensive coach. Baseball has pitching, hitting and fielding coaches. Tennis has serving and footwork coaches.&lt;/p&gt;
&lt;p&gt;In short, there are a lot of skill isolation practices embedded in traditional sports. It makes sense, when you think about it. Coaches may be fantastic at individual aspects of a sport, but not capable of putting the entire piece together for themselves: but they can impart their knowledge to those who can.&lt;/p&gt;
&lt;p&gt;Esports are continually learning from traditional sports: it makes sense to follow in their footsteps in how we train elite individuals.&lt;/p&gt;
&lt;h2 id=&quot;making-the-unintended-deliberate&quot;&gt;Making the unintended, deliberate&lt;/h2&gt;
&lt;p&gt;All professional players have exceptional aim: but for most, it comes without deliberate effort. The risk here is that, without extrinsically understanding what makes you great, these silent habits could disappear, and compromise your skill level.&lt;/p&gt;
&lt;p&gt;From my amateur analysis, ZywOo is a textbook example of “calm aim”, a descriptor within aiming communities to describe players who maintain a low tension within their aim for the majority of their gameplay. This is one of the things that allows him to have the exceptional accuracy that he does. It would be inappropriate to change it, but it might be valuable for him to have the insight into that aspect of his skill.&lt;/p&gt;
&lt;p&gt;Xyp9x, towards the end of his career, demonstrated the exact opposite. Watching him felt like seeing someone vice-grip his mouse, and it meant that during close engagements, his aim would be shaky and inaccurate. At the time I posited that his mouse was too light, but maybe his aiming technique had atrophied during his extended sick leave, and actually, what he needed was an aiming coach to help him understand what had gone wrong, and unlock the aim that he had years ago.&lt;/p&gt;
&lt;h2 id=&quot;what-else-could-you-isolate&quot;&gt;What else could you isolate?&lt;/h2&gt;
&lt;p&gt;As mentioned earlier, aiming has emerged as a mini-industry. Aim coaches and specialised aim training software has emerged to allow players to optimise this specific skill. Aiming has, itself become a competitive game.&lt;/p&gt;
&lt;p&gt;But aiming is hardly the only skill present in Counter-Strike: if it were, aim coaches would be playing the game, rather than helping from the sidelines.&lt;/p&gt;
&lt;p&gt;Take movement. The way that you navigate the map, and position your character, helps give you advantages over your opposition: whether it is getting to a location faster because you efficiently take your steps, or by making your player character as difficult as possible to hit&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. With isolation game modes for movement already existing in the form of KZ, and a plethora of talented individuals within that community, why not enlist one of them to coach you?&lt;/p&gt;
&lt;p&gt;Taking a leaf out of football’s book, what about abstracting aspects of team play? You could translate a set-piece coach into an executes coach. Refrag already has tooling to simulate defending against executes, as well as game modes such as executes&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and retakes. Attack and defence coaches translate into coaches for specific roles.&lt;/p&gt;
&lt;p&gt;But we might be getting ahead of ourselves here.&lt;/p&gt;
&lt;p&gt;For one, budgetary constraints mean that teams may not be able to afford all of this extra personnel. Equally, with only 5 players to coach, it may make more sense for the primary coach to take on these roles. Football teams have 20-30 people to train, and to get playing on the same page, which means that you need assistance. A 5 man team does not face this issue.&lt;/p&gt;
&lt;p&gt;Another caveat is that with 5 players, each player has much more space to play uniquely, compared to football. Taking away that individuality might do more harm than help, if coaches are too prescriptive. It dulls their natural instinct, but also, makes them more predictable and readable. If role coaches do come into fashion, they will need to take care to manage the balance.&lt;/p&gt;
&lt;h2 id=&quot;if-phil-jackson-came-back-still-no-coaching-me&quot;&gt;”If Phil Jackson came back, still no coaching me”&lt;/h2&gt;
&lt;p&gt;ZywOo is one of the all-time Counter-Strike greats. He has never been below the 2nd best player in the world throughout this professional career.&lt;/p&gt;
&lt;p&gt;He is notable in that he doesn’t play deathmatch. He does play KZ and surf, but only for fun. His primary mode of practice is just playing the game as intended, a 5v5 game against other players.&lt;/p&gt;
&lt;p&gt;donk is a phenom, equalling the all-time Big Event record at his debut at Katowice, at the age of 16 years old. He is the best rifler in the world right now. He too does not play deathmatch, choosing to prefer 5v5 competitive games.&lt;/p&gt;
&lt;p&gt;You cannot ignore these two stories. Some of the best talents in the game eschew traditional wisdom, and instead rise to greatness by just playing the game as intended. If these players don’t even play the pre-requisites to employing aim coaching, how can we expect them to go that step further?&lt;/p&gt;
&lt;p&gt;It spills cold water on the idea that aim training is necessary to be a good player.&lt;/p&gt;
&lt;p&gt;Counter-Strike has always looked away from the latest advances in technology. ZOWIE mice, despite having been leapfrogged technically, remain stalwarts amongst top players. Aim trainers have had limited take up, with players sticking to deathmatch, and custom maps such as aim_botz&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Yet despite this, players who struggle to break through in Counter-Strike go on to light up the world in other titles: and this has led to a tradition within CS to keep things the way that they are.&lt;/p&gt;
&lt;p&gt;More than just being exceptions, these players actively inhibit the growth of coaching in the scene. New players will always follow in the example of those ahead of them. From taking configs and gear, copying is rampant, and the routines of professionals are studied by many. EliGE is a truly elite level player, and his uptake of coaching has changed the course of it’s use in Counter-Strike, but until the once-in-a-lifetime player emerges, backed by coaches aplomb, convincing the rest of the scene will be a difficult endeavour.&lt;/p&gt;
&lt;hr/&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;donk’s &lt;a href=&quot;https://www.youtube.com/watch?v=391BV8buysQ&quot;&gt;movement mechanics&lt;/a&gt; have become a massive point of analysis following his stratospheric rise. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;This hasn’t been ported over to CS2, unfortunately. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;It might be unfair to characterise aim_botz as not having once been state of the art. It likely influenced VALORANT’s warm up map. However, aim trainers have evolved to have substantially more depth. &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded></item><item><title>Have CS rounds gotten slower?</title><link>https://bphilip.uk/blog/2023-04-26-have-cs-rounds-gotten-slower/</link><guid isPermaLink="true">https://bphilip.uk/blog/2023-04-26-have-cs-rounds-gotten-slower/</guid><description>An analysis of Counter-Strike rounds over the years.</description><pubDate>Wed, 26 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Counter-Strike events seem to have less energy than ever. There are no concrete statistics to back this up, but the symphonies of Counter-Strike sound more like a small chorale. The crowds have gone from ecstasy, to gentle applause.&lt;/p&gt;
&lt;p&gt;If this is the case, pointing to a single cause is difficult. To list a few changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The makeup of teams has changed, with fan favourites such as NiP, SK and fnatic having all disappeared from the high levels of the scene.&lt;/li&gt;
&lt;li&gt;The local scene had one representative at the top in Virtus.Pro, who have now also disbanded, leaving the Polish crowd little home grown to cheer for.&lt;/li&gt;
&lt;li&gt;COVID might have caused more churn, especially as esports stopped playing offline events and became online only.&lt;/li&gt;
&lt;li&gt;Competition in the tactical FPS market has grown, and as such, the CS audience might have diminished in size.&lt;/li&gt;
&lt;li&gt;Partner teams for big tournaments have reduced the overall quality of competition&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But the way in which the game is played has also changed. Like in running, the equipment available to players has become lighter and more precise than ever. Like in Formula 1, there is an incomprehensible amount of data, with numerous statistical analysis tools to digest it. Like in football, the metagame has evolved, despite the rules of the game being nearly identical.&lt;/p&gt;
&lt;p&gt;Players have learned how to utilize every facet the game has to offer, from grenade timings to elaborate setups for precise smoke placement. The days when smokes were thrown ad-hoc have all but disappeared.&lt;/p&gt;
&lt;p&gt;I want to try and explore some of the ways in which the game has evolved that might have made it less interesting for audiences.&lt;/p&gt;
&lt;h2 id=&quot;what-is-interesting&quot;&gt;What is &lt;em&gt;interesting&lt;/em&gt;?&lt;/h2&gt;
&lt;p&gt;There is no central statistic that can be used to describe what interesting means.&lt;/p&gt;
&lt;p&gt;Interesting to some might be the level of competition, and the number of top teams that exist. Interesting to others might be the way that the mechanics of top players, such as the way in which they aim and throw utility.&lt;/p&gt;
&lt;p&gt;What might give us insight is understanding how individual rounds have changed across the years. If we can point to specific changes in the makeup of a round, we can start to understand ways that viewers might have lost interest.&lt;/p&gt;
&lt;h2 id=&quot;analysis&quot;&gt;Analysis&lt;/h2&gt;
&lt;p&gt;I took demos from all of the CS:GO majors from Katowice 2014, to Rio 2022. Additionally, I included Katowice 2023 to add some 2023 datapoints.&lt;/p&gt;
&lt;p&gt;Caveats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As much as I’ve tried to ensure data quality, this is not a thoroughly tested ingestion pipeline. There may be factual errors. Some demos were removed as they broke the ingestion, but this was minimal.&lt;/li&gt;
&lt;li&gt;Similarly, I’m a relative noob to Pandas,  so the data analysis might be flawed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nonetheless, the conclusions roughly point to what is observable, so my concerns are low on there being systemic issues.&lt;/p&gt;
&lt;h3 id=&quot;rounds-are-longer-on-average&quot;&gt;Rounds are longer on average&lt;/h3&gt;
&lt;p&gt;The average round duration grew from 78 seconds to 95 seconds. Strictly speaking, this isn’t a drastic change, even when compounded over a 30 round game (roughly an additional 8.5 minutes).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/cs-duration.B5tqJNXf_Z24naqj.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;and-saving-is-more-prevalent-than-ever&quot;&gt;And saving is more prevalent than ever&lt;/h3&gt;
&lt;p&gt;Given that a team loses a round, a growth from 0.16 players saving per round to 0.54 players can be observed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/cs-survivingcount.Date_DIF_Z2aJigr.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;p&gt;But the growth is even more drastic when you separate for sides. CT sides, when they know they’re losing a round, on average save nearly a player each time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/cs-savingcountsplit.r4ve92XR_shQms.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;kills-are-spaced-further-out&quot;&gt;Kills are spaced further out&lt;/h3&gt;
&lt;p&gt;The longest wait between kills went from a low of 19 seconds in 2015, to peaking at 27 seconds in 2021. It currently averages at 25 seconds.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/cs-longestkillwaits.CyeNwAba_ZftXhA.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;and-take-place-later-on-in-the-round&quot;&gt;And take place later on in the round&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/cs-killticksrelative.6-Im1PTH_LWxuq.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-last-kill-to-the-end-of-the-round-takes-longer&quot;&gt;The last kill to the end of the round takes longer&lt;/h3&gt;
&lt;p&gt;Previously, when the last kill in a round took place, it took an average of 3 seconds for the round to conclude. This has increased to 10 seconds.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/cs-lastkilltoends.B98KWoog_2vT9FV.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;nades-are-pretty-static&quot;&gt;Nades are pretty static&lt;/h3&gt;
&lt;p&gt;Players are far more effective with their nades, averaging 13 points more damage.&lt;/p&gt;
&lt;p&gt;They’re thrown at virtually the same point in a round. Smokes too, are thrown at virtually the same, moving between 33 and 38 seconds in a round (this does not cleanly go up, unlike the other statistics).&lt;/p&gt;
&lt;p&gt;Molotovs are the notable exception, from being thrown at 41 seconds in a round to a low of 29 in 2022.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/cs-relativenades.SbP68K0c_ZABwBC.webp&quot; alt loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;500&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;whos-saved-the-most&quot;&gt;Who’s saved the most?&lt;/h3&gt;
&lt;p&gt;If we take a look at the players whose teams have saved the most, the most of the top 5 make sense. dupreeh has attended the most majors, and s1mple, olofmeister and Zeus are all players who have made the grand finals multiple times.&lt;/p&gt;
&lt;p&gt;But exceptionally, Jame tops the charts, crushing the competition.&lt;/p&gt;
&lt;h4 id=&quot;players-whose-teams-have-saved-the-most&quot;&gt;Players, whose teams have saved the most&lt;/h4&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Player&lt;/th&gt;&lt;th&gt;Rounds their team have saved&lt;/th&gt;&lt;th&gt;Maps played&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Jame, qikert&lt;/td&gt;&lt;td&gt;289&lt;/td&gt;&lt;td&gt;60&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;dupreeh&lt;/td&gt;&lt;td&gt;257&lt;/td&gt;&lt;td&gt;121&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;s1mple&lt;/td&gt;&lt;td&gt;228&lt;/td&gt;&lt;td&gt;85&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;olofmeister&lt;/td&gt;&lt;td&gt;216&lt;/td&gt;&lt;td&gt;109&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Zeus&lt;/td&gt;&lt;td&gt;212&lt;/td&gt;&lt;td&gt;89&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Dividing by the number of appearances they make in the data set, we can determine what players save most per game. Filtering to a minimum of 20 appearances (to prevent outliers making an appearance), the data continues to show the trend observed - newer players tend to save more, and the Outsiders players are outlier.&lt;/p&gt;
&lt;h4 id=&quot;a-scatter-graph-showing-the-ratio-of-rounds-saved-to-appearances-against-the-average-date-of-their-matches&quot;&gt;A scatter graph, showing the ratio of rounds saved to appearances against the average date of their matches&lt;/h4&gt;
&lt;iframe id=&quot;igraph&quot; scrolling=&quot;no&quot; style=&quot;border:none;&quot; seamless src=&quot;/embed/savingCountVsAvgDate.html&quot; height=&quot;525&quot; width=&quot;100%&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;It takes until 2019 for a player to reach a ratio of 1.5. After that, you have 11 players breach that boundary, with Jame almost reaching a ratio of 3. They aren’t outliers.&lt;/p&gt;
&lt;h4 id=&quot;a-scatter-graph-showing-the-ratio-of-rounds-saved-to-appearances-against-the-first-date-of-their-matches&quot;&gt;A scatter graph, showing the ratio of rounds saved to appearances against the first date of their matches&lt;/h4&gt;
&lt;iframe id=&quot;igraph&quot; scrolling=&quot;no&quot; style=&quot;border:none;&quot; seamless src=&quot;/embed/savingCountVsFirstDate.html&quot; height=&quot;325&quot; width=&quot;100%&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;This graph I find less useful, as you don’t get a sense of what era a player has primarily played within. For instance, cadiaN is at the start of this graph, but the majority of contributions take place at the other end.&lt;/p&gt;
&lt;h3 id=&quot;they-tend-to-take-longer-to-lose&quot;&gt;They tend to take longer to lose&lt;/h3&gt;
&lt;p&gt;We can also look at how long players’ teams take to lose rounds.  Once again, the new school of Counter-Strike takes longer to lose, and once again, Outsiders are outliers.&lt;/p&gt;
&lt;h4 id=&quot;a-scatter-graph-showing-length-of-time-for-a-players-team-to-lose-a-round-against-the-average-date-of-their-matches&quot;&gt;A scatter graph, showing length of time for a players’ team to lose a round against the average date of their matches&lt;/h4&gt;
&lt;iframe id=&quot;igraph&quot; scrolling=&quot;no&quot; style=&quot;border:none;&quot; seamless src=&quot;/embed/roundDurationVsAvgDate.html&quot; height=&quot;525&quot; width=&quot;100%&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;
&lt;h4 id=&quot;a-scatter-graph-showing-length-of-time-for-a-players-team-to-lose-a-round-against-the-first-date-of-their-matches&quot;&gt;A scatter graph, showing length of time for a players’ team to lose a round against the first date of their matches&lt;/h4&gt;
&lt;iframe id=&quot;igraph&quot; scrolling=&quot;no&quot; style=&quot;border:none;&quot; seamless src=&quot;/embed/roundDurationVsFirstGameDate.html&quot; height=&quot;325&quot; width=&quot;100%&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;Similar comment to the above start date graph.&lt;/p&gt;
&lt;h3 id=&quot;what-does-this-show-us&quot;&gt;What does this show us?&lt;/h3&gt;
&lt;p&gt;Rounds take longer, and players save more. The meta shift has been expressed in full by the current generation of players. Arguably, this demonstrates more conservative playing habits - they’re far less likely to take round defining risks.&lt;/p&gt;
&lt;p&gt;None of this is a surprise. The concrete statistics do help us visualize what the change looks like.&lt;/p&gt;
&lt;h2 id=&quot;a-dance-of-interests&quot;&gt;A dance of interests&lt;/h2&gt;
&lt;p&gt;Within any sport, there is a balancing act between providing entertainment value, and providing an avenue for the very best of us to exhibit their otherworldly skills.&lt;/p&gt;
&lt;p&gt;It is not that those things aren’t linked. We watch football because we want to see what the most capable, the most gifted, and the hardest working human beings can achieve against each other within the confines of the game. We watch knowing that if we were to be on that pitch, we would be outclassed. The best managers instrument the orchestra of moves that lead to a goal.&lt;/p&gt;
&lt;p&gt;Yet despite “parking the bus” sometimes being the prudent tactical move, it is widely derided as uninteresting and boring. The very best are executing the ideal strategy, but the outcome causes us to switch off.&lt;/p&gt;
&lt;p&gt;Many consider Virtus.Pro to CS’ equivalent to parking the bus. Slow, methodical, and incredibly effective - but not interesting to watch. Bystanders might fear the effectiveness of this playbook as infecting the rest of the scene, but VP’s failure to qualify for Paris might dissuade others.&lt;/p&gt;
&lt;h2 id=&quot;are-people-turning-away&quot;&gt;Are people turning away?&lt;/h2&gt;
&lt;p&gt;Whether this has any impact on Counter-Strike is difficult to ascertain.&lt;/p&gt;
&lt;p&gt;Viewership in total has grown, breaking new heights every year. But viewership for English language streams appears to have stagnated  since 2017/2018. Atlanta 2018 enjoyed 1.1m concurrent viewers &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, while 2021’s PGL Stockholm enjoyed 954,000 concurrent viewers on the English stream &lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Whether this is a symptom of changing demographics, better quality regional products (one only needs to see the popularity of Gaules), or some other factor, it is impossible to rule out. However, I can tell you that Counter-Strike is a less compelling entertainment product for me, and I’m not sure I’m alone.&lt;/p&gt;
&lt;h2 id=&quot;can-you-change-the-metagame&quot;&gt;Can you change the metagame?&lt;/h2&gt;
&lt;p&gt;Meddling with the game always leads to unintended consequences, but we can look at some ways to shift the playstyle.&lt;/p&gt;
&lt;p&gt;Counter-Strike 2 presents a couple of quick solutions. Smoke grenades can be dispersed by grenades, which adds another level of tactical depth that changes how both of those pieces of utility will be used. Smokes will be less effective, and grenades will be less used for inflicting damage. At the moment, the hitboxes appear to be larger, which could incentivize more aim heavy playstyles as the margin for error drops. Of course, this reduces the skill ceiling.&lt;/p&gt;
&lt;p&gt;Timings could always be changed. In 2015, Valve extended the round timer in competitive play to align with matchmaking. While this was not popular at the time, in retrospect, modern CS would be unplayable with even less time allocated to teams - molotovs and smokes would be more powerful, and teams would pull the plug earlier. But smokes and molotov timings can be modified - making them shorter would reduce the impact they have on the round.&lt;/p&gt;
&lt;p&gt;Monetary incentives for not saving would spur teams into making riskier plays, as the risk/reward balance would shift. Disincentives for saving would also have an effect.&lt;/p&gt;
&lt;h2 id=&quot;a-conclusion&quot;&gt;A conclusion&lt;/h2&gt;
&lt;p&gt;There is no right solution. Counter-Strike 2 gives us enough rope that the best option is to wait and see what it brings. The novelty of the game, despite the closeness to Global Offensive, should bring about a shift in the gameplay. At the time of publishing, Valve have hinted that there is even more to be revealed.&lt;/p&gt;
&lt;p&gt;CS2 could end down the same pathway, however. Should it do so, the time has come to evaluate whether aspects of the core gameplay loop need tweaking to promote more exciting gameplay.&lt;/p&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://archive.is/https://esportsobserver.com/eleague-boston-major-viewership-record&quot;&gt;https://archive.is/https://esportsobserver.com/eleague-boston-major-viewership-record&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.hltv.org/news/32764/pgl-major-stockholm-breaks-records-with-over-27-million-concurrent-viewers&quot;&gt;https://www.hltv.org/news/32764/pgl-major-stockholm-breaks-records-with-over-27-million-concurrent-viewers&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded></item></channel></rss>