[HN Gopher] Wi Flag (2002)
       ___________________________________________________________________
        
       Wi Flag (2002)
        
       Author : corysama
       Score  : 324 points
       Date   : 2023-02-10 17:11 UTC (5 hours ago)
        
 (HTM) web link (asheron.fandom.com)
 (TXT) w3m dump (asheron.fandom.com)
        
       | hesdeadjim wrote:
       | Some of my fondest gaming memories are from this game. There was
       | nothing ever quite like it, and the allegiance system created a
       | special type of community bond that I haven't seen repeated.
       | 
       | At one point I had 10 "vassals" sworn to me, and in our
       | allegiance that came with the expectation that you assist and
       | mentor those under you. Stakes were higher when our allegiance
       | committed to being red dot PKs on a white server with a few other
       | stronger groups in play.
       | 
       | The server emulation scene has come a long way since retail shut
       | down, but even the most populous servers are a pale shade of this
       | game in its hey day.
        
         | loganc2342 wrote:
         | MMOs are just so expensive to develop now that innovation is
         | almost dead. You either make a WoW-like or you die (and many
         | times you die anyway). They really don't make MMOs like they
         | used to.
        
           | dualboot wrote:
           | That's because AC started development before even Ultima
           | Online launched. It was started by a bunch of college
           | students that loved MUDs and had no idea what they were
           | actually doing.
           | 
           | It was such a special thing before it was hit with a lot of
           | road grading over the 15+ years of monthly patching that
           | smoothed a lot of the rough edges that made it really unique.
        
           | tsgagnon wrote:
           | Social media has taken a significant bite out of what I would
           | consider the more important parts of the older MMOs,
           | especially when it comes to apps like Discord. Not enough
           | people want to interact in games anymore outside of specific
           | gameplay scenarios.
        
           | bob1029 wrote:
           | > MMOs are just so expensive to develop now that innovation
           | is almost dead.
           | 
           | I look at this differently. I think the extreme cost of an
           | MMO should _force_ innovation. Take the constraints for what
           | they are and run with them. Accepting that you can 't do it
           | the "traditional" way is the first step to figuring out a
           | better way.
           | 
           | There is nothing that says a high-quality WoW killer
           | absolutely must cost 10 figures to produce.
        
             | Thaxll wrote:
             | It does though, MMO are very complicated to do and there is
             | a lot of tech to build by specialized people. The content
             | is an other issue. You won't build anythinng close to wow
             | bellow 100M.
        
         | gourneau wrote:
         | I also loved this game it was my first MMO, and in many ways
         | was so ahead of its time. I still dream about it occasionally.
        
       | NKosmatos wrote:
       | I enjoy reading such stories, where the software fault (or
       | glitch) is something very simple and easily overlooked. Mind you,
       | this story is from 2002 :-)
        
       | jjcm wrote:
       | Love bug deep dives like these. Along a similar line is the
       | "foxes lead users to treasure" behavior in Skyrim:
       | https://twitter.com/JoelBurgess/status/1428008041887281157
        
       | TheRealPomax wrote:
       | tl;dr: players get attacked based on monster targeting RNG that's
       | _supposed_ to take an interval [0,num_players], assign players to
       | subintervals that are shorter or longer based on a bunch of
       | factors, and then roll a random number somewhere in that full
       | interval. Whoever 's subinterval the number ends in, they get
       | targetted.
       | 
       | Instead, the code assigned subintervals and then rolled a number
       | between 0 and 1, instead of 0 and num_players. If your player
       | happened to sort to the top of the list for subinterval
       | assignment, you'd be it. You'd always be it.
       | 
       | Someone had to think to look at this, then confirm the maths,
       | before it was found, _years_ after the symptoms got reported. A
       | unit test would have caught this, but didn 't. Writing tests is
       | annoying, especially in a codebase that keeps changing, but it's
       | _so_ important that this should count as one of those  "this is
       | what happens when you don't" lessons. Money was lost here.
        
         | squeaky-clean wrote:
         | Was money lost here? Everyone in this thread who played AC is
         | speaking pretty fondly of the bug.
        
         | toast0 wrote:
         | > A unit test would have caught this, but didn't.
         | 
         | Unit tests for things with probability are hard. I've written
         | one recently, and among other reasons, it convinced me to write
         | the selection differently so it was both more 'fair' and more
         | easily tested.
        
         | btown wrote:
         | My startup integrates with numerous third-party data sources,
         | and they'll send quotes in all shapes and colors, usually
         | providing both a total and a complicated breakdown which we
         | need to parse and reshape/classify into line items in our
         | system. And since it's very easy to introduce a bug that skips
         | over a fee accidentally, part of our code review checklist is
         | to ensure that we always explicitly check that our code summing
         | over our final line items sums to the actual ground-truth
         | total; we have a runtime assertion that logs an error to Sentry
         | and, depending on business requirements, shows a (friendly)
         | error rather than incorrect pricing. It's saved us many a time
         | from silly bugs where we're non-exhaustively handling parts of
         | the breakdown data structure.
         | 
         | To generalize, it's vital to have something like Sentry from
         | day one - a low-cost abstraction that lets you monitor broken
         | assumptions asynchronously. Though of course, these kinds of
         | tools didn't exist in 2002!
        
         | thecapybara wrote:
         | > A unit test would have caught this, but didn't
         | 
         | The first unit testing library, JUnit (Java), was released in
         | 1997.
         | 
         | Asheron's Call was released in 1999 after four years of
         | development. It's quite possible that this bug was introduced
         | before the concept of unit testing even existed or was widely
         | known.
        
         | hinkley wrote:
         | > Writing tests is annoying, especially in a codebase that
         | keeps changing
         | 
         | Only if you don't have a functional core.
         | 
         | One of the psychology tricks I've learned about unit testing is
         | just how bad sunk cost fallacy affects some people (all the
         | time, and most people some of the time). I've witnessed people
         | pairing for two days to fix a couple of nasty integration
         | tests. That's 3 person-days of work lost on a couple of tests.
         | How many release cycles would it take for that test to pay for
         | itself versus manual testing?
         | 
         | You want the tests at the bottom of your pyramid to be so
         | simple that people think of them as disposable. They should not
         | feel guilty deleting one test and writing a replacement if the
         | requirements change. Elaborate mocks or poorly organized suites
         | can take that away. Which is hard to explain to people who
         | don't see the problem with their tests.
         | 
         | You also want the sides of that pyramid to be pretty shallow,
         | especially if you keep changing your design.
        
         | jefftk wrote:
         | _> You 'd always be it._
         | 
         | It's slightly more complex than that: if you were farther away
         | or otherwise in a better position than average your portion of
         | the interval would be <1, and so even if you sorted first you
         | still weren't guaranteed to be hit.
        
           | TheRealPomax wrote:
           | Until you were actually taking part in combat and did damage
           | to something, at which point you'd be it.
        
         | SamBam wrote:
         | > A unit test could have caught this
         | 
         | I've always wondered the best way to write tests for "This
         | event should happen x% of the time."
         | 
         | Obviously we could re-run the test 100 times and see if it
         | happened _close_ to x%, but not only is that inefficient, how
         | close is  "close"? You'll get a bell curve (or similar), and
         | most of the time you'll be close to x but sometimes you'll be
         | legitimately far away from x and your test will fail.
         | 
         | You could start from a known seed, but then are you really
         | testing the percentages, or just checking that the RNG gives
         | you the same output for the same seed, which you already know?
        
           | pkhuong wrote:
           | > I've always wondered the best way to write tests for "This
           | event should happen x% of the time."
           | 
           | I use https://github.com/pkhuong/csm/blob/master/csm.py to
           | set a known false alarm rate (e.g., one in a billion) and
           | test that some event happens with probability in a range [lo,
           | hi], with lo < expected < hi (e.g., expected +/- 0.01). The
           | statistical test will run more iteration as needed. If that's
           | too slow, you can either widen the range (most effective), or
           | increase the expected rate of false alarms (not as effective,
           | because the number of iteration scales logarithmically wrt
           | false alarms).
        
           | perlgeek wrote:
           | This is pretty hard to black-box test.
           | 
           | What would have helped in this case:
           | 
           | * Test that all players _can_ be selected by the algorithm at
           | all
           | 
           | * Test that the totals of the weights is the same as the RNG
           | max range
        
             | hinkley wrote:
             | Scatter plots are good when you can't exhaustively test.
        
           | hashkb wrote:
           | You can mock the RNG. You don't need to test/prove it's
           | random, you need to test your code which is not random.
        
             | hinkley wrote:
             | unit tests are notoriously bad about testing n>2. I just
             | ran into a problem with sorting recently that was caused by
             | buggy comparators, but it didn't bubble up to the tests
             | until the runtime switched to a different sort
             | implementation. Most of the tests were doing n=2 so it was
             | not visible under the old runtime version but was under the
             | new one. This has been broken in production for months if
             | not years. If the test had used n=5 I'm pretty sure the old
             | tests would fail as well.
        
           | delecti wrote:
           | You would probably not test "happens x% of the time", but
           | rather that for a given set of inputs, passing in 0.1, 0.2,
           | 0.3, etc, let you have the expected outcomes across the
           | distribution. So you're testing that you can achieve each
           | outcome across the spectrum with a pre-selected "random"
           | number.
        
           | OkayPhysicist wrote:
           | I'm not a fan of the set-seed solution. In the past, when
           | I've tested PRNG implementations (Erlang used to not have the
           | ability to have multiple, independently seeded RNGs), my
           | approach was to decide on an acceptable rate of false
           | negatives, and design my test around that. I figured I'd run
           | the test suite no more than 10,000 times, and I wanted a
           | 1/1,000,000 chance of ever seeing a false negative.
           | 
           | I can't remember the exact math I used at the time (I had to
           | crack open a stats textbook), but ultimately it boiled down
           | to generating a bunch of (seed, number of values previously
           | pulled based on that seed, value) tuples, running a linear
           | regression against them, and defining a maximum acceptable
           | R^2 value based on my 10^-30 acceptable probability of a
           | false fail.
           | 
           | When the RNG is not the thing being tested, mocking the RNG
           | to do a sampled sweep through the RNG's output range is
           | typically the correct move.
        
           | jerf wrote:
           | In the similar situations I've run, what I've often done is:
           | 
           | 1. Start with a known seed. 2. Run a single test run like
           | what you say, and verify this run by hand. 3. Freeze the test
           | in this state, that is, assert you get that exact result
           | every time on the given seed.
           | 
           | What this creates is not what I would strictly speaking call
           | a "unit test", but it _does_ sort of pin the algorithm to
           | your examined and verified output. In this case, a human
           | would quite likely have caught this problem on a decent test
           | set. Obviously, there are other pathologies that would slip
           | right by a human; the human being careful only raises the bar
           | for such pathologies, it doesn 't completely eliminate them.
           | 
           | But at least freezing it solves the problem where a change
           | you did not realize would be a change slips by unnoticed and
           | this function suddenly has a completely different outcome.
           | 
           | This has worked for me, in the sense it has caught a couple
           | of bugs that would have had non-trivial customer
           | implications. But I've never worked on an MMORPG or anything
           | else where randomness was intrinsic to my problem; it has
           | always been incidental, like, is my password generation
           | algorithm correct and does this sample of my data look like
           | what I expect, not the core of my system.
        
         | rcme wrote:
         | The RNG was supposed to generate a random number in [0, sum of
         | weights] not [0, num_players].
         | 
         | It's also possible to write a test for this where the behavior
         | in the test accurately tests the wrong behavior. The error is
         | pretty subtle. There was even a "bug" in your summary of the
         | bug ;)
        
         | EarthLaunch wrote:
         | Is it so important? I think this made the community and game
         | world more interesting. It's emergent behavior. As a game
         | developer, I hope I can make things complicated enough to have
         | emergent behavior, even if that's just from my bugs.
        
           | TheRealPomax wrote:
           | You know what would have made it even better though? Not
           | having a bug that made your character cursed through no fault
           | of your own without any recourse.
        
             | claytongulick wrote:
             | Would it have?
             | 
             | Now a player named Wi is still the subject of conversation
             | on at least two major online discussion forms over 20 years
             | later.
             | 
             | From what I've read, it introduced quirkiness and a bunch
             | of unintentional community involvement, with likely much
             | hilarity.
             | 
             | The goal of playing a game is to have fun.
             | 
             | Dealing with frustration can also be fun, in fact the Dark
             | Souls series recognized this brilliantly.
             | 
             | This bug, while undoubtedly frustrating, sounds like it was
             | also a lot of fun for a lot of folks.
        
       | thomasskis wrote:
       | The bugs in this game lead to some of the greatest gameplay of
       | all time.
       | 
       | I think the best bug was the movement possibilities during spell
       | casting from breaking animations. It created one of the most
       | complex and amazing PK (PvP) dynamics of any MMO to exist.
       | 
       | The complexity of being able to move only so much to still get
       | your cast off, and being able to slightly fast-cast or hold long
       | delay-casts to "outplay" your opponents created so much depth to
       | duels it was incredible.
       | 
       | Even after all these years I can still remember the Arc cast I
       | would do, it was the keyboard combo: Hold Left -> Hold Z -> X ->
       | tap/hold up to control the radius Then Hold Right -> Hold C -> X
       | -> tap up to reverse the arc to return to where you initiated the
       | cast so the spell could go off.
       | 
       | Man I miss this game, I hope someone creates a wonderfully buggy
       | remake someday!
        
         | thomasskis wrote:
         | If anyone remembers the days when guys like "Rookie" or the
         | UD's figured this out and mastered it, what a time to be alive!
         | Good ol' AB wars... :)
        
           | thomasskis wrote:
           | Wow I had to go on a nostalgia tour and I found a Rookie
           | classic: https://www.youtube.com/watch?v=FwpujtVM6R8
           | 
           | Bugs really made this game one of a kind, it's sad it would
           | be so hard to replicate. The way he uses strafing and delay
           | casting on corners to fight odds is amazing.
           | 
           | I still remember my hands shaking when I was in PK fights
           | like this in my youth. The consequences of death made
           | fighting so much more intense in this type of MMO.
        
       | [deleted]
        
       | jdk wrote:
       | Really didn't expect to see AC at the top of HN. Asheron's Call
       | was the first game I worked on and I remember all the times we'd
       | joke with Wi about it and watch monsters beeline for him. It
       | seemed like one of those "Haha sure, player perception" problems
       | and not something that was actually real. IIRC someone did a very
       | cursory look at the code at one point but it never bubbled up as
       | important enough to assign someone to to actually investigate.
       | 
       | Wi came to one of the player gatherings with little printed out
       | cards and would hand them to people and say, "You've been Wi
       | flagged!"
       | 
       | The fondest of memories.
        
         | berkle4455 wrote:
         | Sorry, who is Wi?
        
           | johnnyo wrote:
           | "Wi" was An early player of the game that was the a victim of
           | the bug. His character's name was Wi, and the bug was named
           | after him.
           | 
           | I remember people theorizing it was due to a short name (only
           | 2 characters), and so would create longer usernames to try
           | and avoid the "curse"
        
         | blipmusic wrote:
         | Min-max:ed dagger warrior for the win! Also, fear the ash
         | gromnie! AC was never really trumped for me (AC2 was...
         | different?). I just wanted a world to roam, and the vassal
         | system is probably the only pyramid scheme that incentivised
         | making social connections. :) My patron did a lot corpse runs
         | for me.
        
           | jdk wrote:
           | For the last 15 years or so, coworkers ask when I'm going to
           | make a new allegiance system but "less broken". So many good
           | social behaviors came from its structure that it really
           | deserves another attempt.
           | 
           | And yeah, Ash Gromnies were the bane of so so so many
           | players.
        
         | jdwithit wrote:
         | I loved Asheron's Call, played it a lot back in the day. My
         | friends and I were in high school at the time so we had
         | absolutely no idea what we were doing, but that didn't stop us
         | from running around the world goofing off. My hobby was making
         | characters with totally insane Run and Jump skills. Once you
         | leveled up enough you could literally leap from one end of a
         | town to the other like Superman, it was extremely funny. The
         | character was awful in all other regards, but I didn't care. I
         | made another character whose sole purpose was to climb to the
         | top of the highest cliff or building I could find, and jump off
         | it. And there were some HIGH places in AC. I miss being able to
         | play MMO's innocently like that rather than trying to min-max
         | every last bit of efficiency out of everything, as embodied by
         | WoW (another game I loved, but for different reasons).
         | 
         | I also really enjoyed the periodic story events that had really
         | dramatic impacts on the world, like the shadow invasion. It was
         | a great game, especially for its time. So thanks for whatever
         | part you played in its creation.
        
           | jdk wrote:
           | Thanks! Always nice to hear people who "grew up" play it. AC
           | having server-side physics and actually making use of them
           | led to lots of ridiculous and emergent gameplay. I don't know
           | how many hours I just spend idling in towns jumping from
           | rooftop to rooftop or seeing how high I could climb up
           | massive structures. Everytime I try to play again though, the
           | old "you can't go home again" hits too hard and I just
           | quietly close it back up and go back to the nostalgia.
           | 
           | I was on the design team, so was directly responsible for a
           | lot of the shadow invasion stuff (if you ever saw the big bad
           | Bael'Zharon running around in the live events, that was me!)
           | and other patches for the first 2 years of its lifespan.
           | 
           | Weirdly, I work on WoW now with my career having come full
           | circle after having not worked on MMOs since the mid 2000s.
           | :)
        
             | yvdriess wrote:
             | Another "grew up playing AC" here and fondly remember
             | interacting with Bael'Zharon on the Harvestgain server
             | during the life events. Did you also blow up Arwic? :D
             | 
             | I still use AC and to some extent AC2 as an example of how
             | wild, weird, dynamic and interesting MMOs were before the
             | EQ formula won through WoW's success.
        
         | Naomarik wrote:
         | AC was my first MMORPG, fond memories indeed. I remember the
         | sheer adrenaline I got when "going red" and watching PK drama
         | and battles unfold at the subway, dominated by a build called
         | the "OG mage," slidecasting all over the place casting drain
         | health until finishing with a missile spell. I would cast
         | Blooddrinker 6 on monster weapons and giddily laugh as they
         | sliced through new players starting out. I remember staying up
         | the entire night during a school day when housing was released
         | and being one of the first people on my server to claim one. I
         | even remember being a vassal to a very generous asian guy in
         | his mid twenties living in LA named Kyoto and my countless
         | interactions with him and his brother under a specific tree.
         | 
         | Countless memories I could keep going on and on, but what an
         | experience!
        
           | picowatt wrote:
           | Some of my favorite memories as a kid were playing Asheron's
           | Call. Incredible game.
        
           | jdk wrote:
           | Haha "Og mage" ... yeah. The combat of AC still holds up in
           | its janky for being fun in the context of an MMO. I spent
           | most of my playtime on Darktide and dear lord, it made me so
           | sweaty.
           | 
           | It's amazing to me how many people are still friends with
           | their patrons/vassals from 25 years ago.
        
         | nevir wrote:
         | AC was such a fantastic game and community - props to all you
         | at Turbine that worked on it. So many great memories for me!
        
           | jdk wrote:
           | Thanks! Glad it holds a special place for you :)
           | 
           | In retrospect, I give a lot of credit to the fact that we
           | were young and dumb and didn't know any better. I've been
           | revisiting a lot of the stories from back then and so many of
           | them end up with us saying, "I dunno, let's see what
           | happens!" and not being dissuaded by "best practices" or even
           | common sense.
           | 
           | Also lots of credit goes to the early internet era when
           | people were a LOT more forgiving of, well, everything.
        
       | dylanpyle wrote:
       | I've seen a similar mistake in a rushed "feature flagging"/phased
       | rollout system.
       | 
       | User IDs were random UUIDs. Let's say we want to release a
       | feature to ~33% of users; we take the first 2 characters of the
       | UUID, giving us 256 possible buckets, then say that everyone in
       | the first 1/3 of that range gets the feature. So,
       | 00XXX...-55XXX... IDs get it, and 56-FF do not. This works fine.
       | 
       | However, if we then release another feature to 10% of users -
       | everyone from 00-1A gets it, 1B-FF do not. That first set now has
       | both features, and 56-FF have none. It turns out you can't draw
       | meaningful conclusions when some users get every new feature and
       | some get none at all.
        
         | tmoertel wrote:
         | One easy way to avoid this problem is to give each feature its
         | own independent space of "dice rolls" by hashing the user ids
         | with feature-specific constants before interpreting them as
         | dice rolls:                   feature1_enabled = hash(user_id +
         | "-feature1") / HASH_MAX < 0.3;  # 30% of users.
         | feature2_enabled = hash(user_id + "-feature2") / HASH_MAX <
         | 0.1;  # 10% of users.
        
           | phreeza wrote:
           | If you suspect some flag effects interact with each other
           | (e.g. one flag increases button size by 10%, and the other
           | decreases it by 10%) you can go one step further and define
           | feature groups and hash by user-id + group-id and then assign
           | non overlapping ranges to the flags.
        
             | marcosdumay wrote:
             | Or you can cut and redistribute the non-performing changes,
             | increase the distribution of the well-performing ones, and
             | let evolution take care of disentangle correlated behavior.
             | 
             | But if need that kind of analysis for usability A/B
             | testing, you most be doing something very wrong on a
             | previous step.
        
           | groestl wrote:
           | For reference:
           | https://en.wikipedia.org/wiki/Consistent_hashing
        
             | singron wrote:
             | How is that related?
        
               | groestl wrote:
               | Consistent hashing (or more generally weighted rendezvous
               | hashing) provides pseudorandom allocations with minimal
               | reallocations when parameters change. This is exactly the
               | properties desired for rolling out feature flags
               | gradually over an input space like user IDs. It is a
               | special case of a consistent hash function, where the
               | possible assignments are just two (weighted) buckets,
               | corresponding to the feature flag's value of true/false.
        
         | Eduard wrote:
         | > That first set now has both features, and 56-FF have none. It
         | turns out you can't draw meaningful conclusions when some users
         | get every new feature and some get none at all.
         | 
         | 00--1A: have feature flags A and B
         | 
         | 1B-55: have feature flag A only
         | 
         | 56-FF: have no feature flag
         | 
         | So the actual gotcha here is that there is no cohort for
         | "feature flag B only", right?
         | 
         | This setup can actually be desirable if feature B depends on
         | feature A.
        
           | duskwuff wrote:
           | > So the actual gotcha here is that there is no cohort for
           | "feature flag B only", right?
           | 
           | And that, as you add more tests, user 00 will always get the
           | test treatment for _every_ test. If you 're running a lot of
           | tests which introduce experimental features or changes to
           | workflows, user 00 is probably going to find the site a lot
           | more chaotic and hard to understand than user FF, and that
           | will skew your test results.
        
           | dylanpyle wrote:
           | > So the actual gotcha here is that there is no cohort for
           | "feature flag B only", right?
           | 
           | Yep, exactly - by "that first set" I meant the 00-1A group,
           | could have been clearer. Whatever the smallest rollout bucket
           | is, that group is guaranteed to have every single feature.
           | 
           | This was quite a while ago, but I think the actual case we
           | noticed this with was several features released to 50% of the
           | userbase - so every single user either had all or none at
           | once (unintentionally)
        
         | xmonkee wrote:
         | Huh, thanks for this. Will live in my head from now. Basically,
         | in this situation, use (user_id, feature_name) for hashing, not
         | just the user_id.
        
           | dekhn wrote:
           | Is there a more general term for tuple hashing? IE, math and
           | theory around composition of hashes composed of concatenated
           | (or otherwise combined) typed values?
        
           | yiuywieyrw wrote:
           | A better way is to assign some internal salt to the feature
           | at creation time and use that, that way you are not dependent
           | on something external that user (the creator of the feature
           | flag) could change. I bear the scars of this design mistake
           | from when I worked for a company that provided feature
           | flagging. It was not my initial mistake, but I drew the short
           | straw trying to work around it.
        
             | xmonkee wrote:
             | Solid tip, again.
        
           | dabeeeenster wrote:
           | Haha funnily enough that is our (Flagmsith's) exact
           | algorithm!
        
         | [deleted]
        
       | anyfoo wrote:
       | Around 15 years ago, when casual little games on Facebook were
       | still a thing (actually when Facebook itself was still a thing),
       | I used to play Yahtzee on the site while watching TV shows or
       | whatever. It was one of the most popular games on there. For me
       | it was something to fidget with (there was no money involved or
       | anything, just a personal high score), so I played it a lot.
       | 
       | I felt more and more that dice values of specifically 1 and 6
       | were harder to come by than other values, so one day I sat down
       | for a few minutes and logged the value of 100 or so dice throws.
       | Turns out I was right, the distribution was not uniform: 2-5 were
       | fine, but it seemed that it was _twice as hard_ to get a 1 or a 6
       | compared to any other value.
       | 
       | I even did a chi-squared hypothesis test, because I was crazy.
       | (And because I was studying for my statistics minor in university
       | at the time).
       | 
       | Seeing the result, the problem was pretty clear, without even
       | knowing the source code. Almost certainly, they had a random
       | number generator giving a number in a uniform range, let's say
       | from 0 to 1, and did something like the following to get a dice
       | value from 1 to 6:                  value = round(random()*5)+1
       | 
       | Do you spot the issue?
       | 
       | The problem is that round() rounds to the _nearest_ integer. So
       | any value between, say, 1.5 and 2.5 (exclusive at one end) rounds
       | to 2, 2.5-3.5 rounds to 3, and so on. Add 1, and you have the
       | dice value.
       | 
       | But the ranges for dice values 1 and 6, are only 0 to 0.5 and
       | 4.5-5 respectively, so ranges that are only half the size.
       | 
       | The fix should be extremely simple:                  value =
       | floor(random()*6)+1
       | 
       | The crucial point being to use floor() or ceil() instead of
       | round(), to only round towards one direction.
       | 
       | I wrote up exactly this in a short email to the company that made
       | the Yahtzee game. They did not reply and just silently fixed the
       | bug, right after my email. I was disappointed and stopped
       | playing.
        
         | phailhaus wrote:
         | You stopped playing because they listened to you and fixed the
         | bug for everyone?
        
           | altairprime wrote:
           | They didn't say "thank you", which for many humans is
           | demoralizing.
        
             | xen2xen1 wrote:
             | And at that point he'd played the game a lot, so he
             | probably would have quit playing anyway. Were he like me,
             | the fun at that point was the statistics portion anyway,
             | and he'd already found and fixed that, so it was no longer
             | fun either.
        
           | anyfoo wrote:
           | After I (happily!) did their work for them, a simple "thank
           | you", or even an acknowledgment through a closed ticket,
           | would have entirely sufficed to make my day.
        
             | kvark wrote:
             | Or maybe the bug was closed as a duplicate of one they were
             | already aware of? Still impolite of them, of course, but we
             | shouldn't assume the worst.
        
               | [deleted]
        
             | rcfox wrote:
             | Back when Stack Overflow was in beta, the original design
             | was really rough, so I mocked up a suggested new design for
             | the main page via Stylish and submitted it to them. Within
             | a day or two, they adopted something almost identical but
             | never acknowledged me. One could argue it was a pretty
             | basic idea (I only spent around 15 minutes on it myself)
             | and they probably arrived there independently, but I still
             | like to believe that I influenced a major site's design.
        
           | 30minAdayHN wrote:
           | Because they lacked decency and intellectual humility to
           | acknowledge his email despite benefiting from it.
        
             | tablespoon wrote:
             | > Because they lacked decency and intellectual humility to
             | acknowledge his email despite benefiting from it.
             | 
             | Or their internal communication was haphazard and not
             | designed to handle this case. I could totally imagine the
             | bug report getting passed informally through a game of
             | telephone and losing the connection to the external
             | reporter (e.g. at some point the report got paraphrased, so
             | the developer who fixed it doesn't know where the report
             | came from, and the person who received the initial report
             | doesn't know if it had merit or if it was fixed).
        
           | narag wrote:
           | I sent a patch to a bigger and more known software company,
           | now defunct. I ended up writing some rude comments in the bug
           | submitting form, after being forced to enter endless data
           | about me, the company that I worked for and a lot of
           | information about how to reproduce the error. Not proud of
           | it, but I understand the GP: you're helping them and they
           | treat you poorly.
           | 
           | They included the fix in the next version of the tool. I
           | later noticed it was incomplete, but this time I just made
           | the correction locally.
        
             | macintux wrote:
             | It is quite maddening to have to provide personal
             | information to report a bug. My city stopped allowing
             | anonymous reports of broken traffic lights, so every time I
             | report one (much rarer now that they've made it harder) I
             | always give bogus information.
        
               | idontpost wrote:
               | Hey look Jimbob! The consultant says if we added
               | obnoxious paperwork requirements, there'd be fewer broken
               | traffic lights! I don't know how that's possible, but by-
               | golly it worked!
        
               | jfk13 wrote:
               | Wow ... how often do traffic lights break in your city?!
        
               | macintux wrote:
               | I see a burnt-out bulb at least once a week.
        
               | jfk13 wrote:
               | Interesting. I feel like it's something I've only seen
               | _very_ occasionally - I don 't remember when I last
               | noticed one. Maybe you just have a much higher density of
               | traffic lights where you live, which would make it more
               | common to see failures; and/or maybe they're a different
               | type or differently maintained.
        
               | sublinear wrote:
               | https://youtube.com/watch?v=GiYO1TObNz8
               | 
               | Technology Connections
               | 
               | The relevant part about the old incandescent bulbs is at
               | 3mins 14secs
        
           | [deleted]
        
         | bscphil wrote:
         | > I wrote up exactly this in a short email to the company that
         | made the Yahtzee game. They did not reply and just silently
         | fixed the bug, right after my email. I was disappointed and
         | stopped playing.
         | 
         | I love this. It's one of those things that's entirely
         | intelligible to me but I imagine would be next to impossible to
         | explain to a Martian.
        
         | [deleted]
        
         | lucasmullens wrote:
         | Interestingly that Yahtzee version was rigged in the player's
         | favor since they're more likely to get X-of-a-kind if the same
         | numbers appear more often. Average scores probably dropped a
         | decent bit after that fix.
        
           | anyfoo wrote:
           | For the short time that I knew about it and it was not fixed
           | yet, I integrated it into my strategy. 1 and 6 are rare, so
           | if for example I still needed them for something, I was
           | inclined to make good use of 1 and 6 when they came up,
           | instead of rerolling them for something else.
        
       | nluken wrote:
       | I love hearing about bugs like this one. It's a nice reminder of
       | the problem solving that made me fall in love with computer
       | programming, which sometimes gets obscured in the day-to-day
       | processes of working on software.
        
       | [deleted]
        
       | GuB-42 wrote:
       | It reminds me of the "charm tables" of some Monster Hunter games.
       | Charms are equipment with randomly selected skills. When you
       | create a character, you are assigned a random "table" and all
       | charms you may get are selected from that table. There are 17 of
       | them, 12 of them are normal with some slightly better suited to
       | some play styles but it is a really minor thing, the remaining 5
       | are called "cursed tables", they are much smaller and you will
       | never be able to get the best charms. It is not game breaking,
       | but it is annoying if you want a highly optimized build.
       | 
       | The reason it happen is that the random number generator has only
       | a small state (I think 16 bits) a limited number of possible
       | rolls, and some seeds have a really short period, which limits it
       | even more. Also, the seed is stored in your save file. It means
       | that if you have a bad seed, you will always have a seriously
       | broken RNG and the only way to change that is to create a new
       | character. I think in later games, the same terrible RNG is used,
       | but a new seed is picked each time you start the game, so you
       | won't stay in the same "table". And while "charm tables" are the
       | most obvious consequence, if probably has other, less noticeable
       | effects on gameplay.
       | 
       | The weird part is that while it is obviously a bug as it
       | negatively affects the experience of some random players, it is
       | rarely referred to as such. It even persisted between versions.
       | Some people even wrote tools to find out early on which table you
       | are, and techniques to get the table you want, along with a
       | variety of RNG manipulation exploits.
        
         | tm-guimaraes wrote:
         | Yes, Monster Hunter 3 Ultimate had the permanent table. While 4
         | was for game session.
        
       | arduinomancer wrote:
       | I totally get how this bug would end up in the game
       | 
       | Someone probably manually tested the feature originally and
       | thought "yeah this feels random"
        
       | BryantD wrote:
       | Sandra Powers (who finally figured the problem out) and her
       | husband have been writing and running their own MMO for quite a
       | while now. Check out http://projectgorgon.com/ if you're
       | interested in something handcrafted, quirky, and high quality.
        
         | tsgagnon wrote:
         | Wow, I had definitely forgotten that was being worked on still,
         | it's been a long time since I've played it.
         | 
         | Also reminded me that I backed Camelot Unchained that's still
         | kicking around in development after all these years.
        
         | don_neufeld wrote:
         | I had the pleasure of working with Sandra at SOE for a while on
         | EverQuest II, and later I contracted with her and Eric to help
         | at my startup Ohai. They are both wonderful people and it's
         | great to see this game is still ongoing.
        
         | DanHulton wrote:
         | I keep forgetting about this game and meaning to go back to it.
         | Definitely the "weirdest" (in a good way!) MMO out there.
        
       | Aeolun wrote:
       | Hmm, when they told me they were assigning people to a list I
       | kind of knew what the answer was going to be.
       | 
       | What is curious is that it took them a long time to find. I'd
       | think that -as long as you believe there is a bug- this should be
       | fairly straightforward to spot.
        
         | hinkley wrote:
         | > I'd think that -as long as you believe there is a bug- this
         | should be fairly straightforward to spot.
         | 
         | This is the power of continuous integration.
         | 
         | There's a certain amount of optimism needed to keep going as a
         | software developer, and then there's the crippling amount of
         | optimism that a lot of people have which makes for difficult
         | team dynamics. CI says it doesn't matter if it works on your
         | machine, it's red on a neutral box so fix your problems or it's
         | not going into the release. It's much harder to ignore Jenkins
         | than to ignore David.
         | 
         | People learn through trial and error that the Wally Filter
         | works on bugs, so denial is their first and best defense. Prove
         | to me there's a bug. I won't spend any time on it until you do.
        
         | ok_dad wrote:
         | I was waiting for them to say something like "then we take the
         | random variable and multiply it by 3 to correct for this" and
         | then explain some other, more subtle, bug. Looks like we all
         | make stupid mistakes like this sometimes. I made a bug where I
         | tried to get the month number for the next month, so you had to
         | wrap at 12, but I just did "(current_month + 1) % 12" and left
         | it at that, thinking for some reason that modulo works
         | differently than it does in reality. Some stuff broke recently,
         | due to that, and it was quite embarrassing.
        
           | Aloisius wrote:
           | I must be missing something. That is how modulo works. Well
           | as long as January is month 0.
        
             | SoftAnnaLee wrote:
             | It seems that the issue is that `January === 1`; so when
             | you get to December (i.e. `12`) it rolls over to 0 rather
             | than remaining as 12.
        
         | Goronmon wrote:
         | I could be remembering incorrectly, but back when this was
         | occurring no one knew that issue was specifically limited to
         | "mob spawns attacked certain people". The more honest
         | description is the line about "From the beginning of AC, some
         | players have complained about unbelievably bad luck."
         | 
         | People blamed this behavior for everything from loot drops, to
         | combat outcomes, and to aggro mechanics.
         | 
         | And also remember that AC was before MMOs became massively
         | popular, and outside of specific events and locations, there
         | wasn't always more than a handful of players in a certain area
         | for a given server where aggro mechanics like this would
         | matter.
        
       | ergonaught wrote:
       | I miss AC so much it hurts.
        
         | dualboot wrote:
         | https://emulator.ac/ =)
        
         | thomasskis wrote:
         | I dream of the day when I can ask an LLM to write a modern
         | version of AC in Unreal 7... Exploring Dereth with reality
         | level detail would be incredible.
        
       | veilrap wrote:
       | I love the "lore" that this sort of bug creates, especially in
       | these sorts of large scale multiplayer environments.
       | 
       | Players claiming to be cursed, and the curse was real!
       | 
       | A very different sort of event that it reminds me of is the old
       | World of Warcraft plague:
       | https://en.wikipedia.org/wiki/Corrupted_Blood_incident
        
         | LelouBil wrote:
         | Great read, thanks for sharing !
        
         | iamdbtoo wrote:
         | My theory for why people think they are being "shadowbanned" or
         | otherwise targeted by a social media company is often because
         | of bugs like this. They are weird and almost like gaslighting
         | in the way you experience them and people who don't understand
         | how these bugs can exist assume sinister motives.
        
           | nyanpasu64 wrote:
           | Shadowbanning is a very real phenomenon; my current Reddit
           | account was shadowbanned _twice_ because I had created and
           | posted memes which got unusually high upvotes for a new
           | account, and the algorithm thought I was a bot reposting
           | images to farm karma for future spamming. And from time to
           | time I see HN users whose posts are flagged by default. I 'm
           | less sure if/how shadowbanning occurs on Twitter.
        
             | kevingadd wrote:
             | The problem is that while shadowbanning is a real thing,
             | there are lots of bugs that also appear to be shadowbans
             | and might just be a momentary glitch or an unintended
             | interaction between systems. In Twitter's case, there are
             | multiple different penalties that can apply to account and
             | people refer to them all interchangeably as a "shadowban".
             | And some people claim to be shadowbanned when as far as
             | anyone can tell there's no function in Twitter's system to
             | do it, there's just something weird happening in the
             | infrastructure or algorithms (or it's all imaginary, who
             | can say)
        
               | mistermann wrote:
               | Or it is actually real and it is those who are imagining
               | it to be only imagined who are mistaken. Almost
               | everything we do is composed of substantial imagination,
               | _the whole system runs on it_.
               | 
               | What I find interesting is the substantial curiosity and
               | effort people will put towards solving questions in video
               | games, but when asked to solve problems in the game of
               | life that we are embedded in, people often seem to have
               | opposite instincts.
        
         | shadowgovt wrote:
         | One of my favorite things in gaming is when lore develops from
         | bugs.
         | 
         | When they added the ability for Kerbals to be killed in Kerbal
         | Space Program, they tripped over a bug where the first Kerbal
         | in the game's engine, Jebediah (the one who dated back to the
         | original introduction of astronauts at all, where only one
         | existed), could not be killed. Because of some of the game
         | logic having gone unmodified from the earlier versions, some
         | operations would cause him to be loaded into the pilot seat and
         | those operations didn't check if he was deceased. As a result,
         | you could lose him on a mission only for him to spontaneously
         | appear at the controls of another mission.
         | 
         | The community responded with fan-art of "Jebediah Kerman,
         | thrillmaster."
        
           | marcosdumay wrote:
           | The KSP community has lore about the Kraken. They will joke
           | about anything.
        
       | downvotetruth wrote:
       | What does "Wi" stand for in the stamp? Would have been better to
       | have a flag of freshmeat.
        
         | trynewideas wrote:
         | Apocryphal but as valid as anything when it comes to MMO
         | terminology:
         | 
         | https://forums.ddo.com/forums/showthread.php/264543-Wi-Flag-...
         | 
         | > Anyone who played Asheron's Call probably heard of the AI bug
         | associated with monster Aggro where a person name "Wi" was
         | forever cursed with getting the aggro no matter what.
        
         | hesdeadjim wrote:
         | From what I recall it was a character named Wi who was
         | persistently vocal about it.
        
           | dualboot wrote:
           | This is the correct answer. Wi was a prolific blogger and fun
           | personality.
        
             | Sivart13 wrote:
             | would love to know how "bad" Wi's hash actually was, like
             | what percentile of the users DB sorted higher/lower than it
        
         | emdashcomma wrote:
         | One of the impacted players had an in-game character named Wi.
        
         | BryantD wrote:
         | As trynewideas says, "Wi" was the name of the player who
         | famously described this problem. Source: I worked for Turbine
         | at the time.
        
       | jefftk wrote:
       | (2002)
        
       | Goronmon wrote:
       | Strange to see this exact topic come up twice in two days (the
       | other on Reddit).
       | 
       | But as a huge fan of the original AC, it's always fun to see it
       | come up still.
        
         | jedberg wrote:
         | Most likely someone saw it on reddit and posted it here. :)
        
       | karaterobot wrote:
       | So it's not really a flag, it's that the algorithm that
       | determines who the monsters attacks had a bug. The bug made it so
       | that when there were a group of players to choose from, the mob
       | would always pick players whose (hashed) identifier was higher on
       | the list. Since the hash of your ID doesn't change, those players
       | would always get picked on first. Like if your name is Aaron A.
       | Aardvark, you're always coming first on any alphabetized list.
        
         | dmurray wrote:
         | But it wouldn't always pick them, it would pick them with a
         | higher probability that also depended on the players' relative
         | distances to the monster.
         | 
         | So it's a stochastic bug where any given occurrence can be
         | explained as "you just have confirmation bias, you don't notice
         | all the times Zygy Zebra gets attacked" or "you must have been
         | closer than Zygy even though you thought you were a bit further
         | away". Especially if the game has a first-player perspective
         | which makes it harder to estimate whether you or another player
         | is closer.
        
       | Papychulo0217 wrote:
       | [flagged]
        
         | susrev wrote:
         | Really?? Scams On HN now?
        
       | kypro wrote:
       | What am I missing here? Unless all the devs were really bad at
       | maths (unlikely if they're game devs) then this seems like a
       | really easy bug to find all things considered?
       | 
       | I thought maybe it was going to be some weird DB glitch or
       | something far upstream from the algorithm selecting which player
       | to attack, but it was literally the logic of the very algorithm
       | you would first look at if you were aware of such an issue.
       | 
       | This was a fun read though. Finding and fixing bugs like this is
       | some of the most satisfying work we do imo, and no one outside of
       | tech understands =)
        
         | mabbo wrote:
         | It's game code that was written in the late 90s. Unit tests
         | aren't very likely. And a quick glance at the code probably
         | looked completely sane.
        
         | hinkley wrote:
         | I'm missing something here and it has nothing to do with math.
         | 
         | Why couldn't they reproduce the problem in testing? For what
         | was it, years?
        
           | voakbasda wrote:
           | Likely because they tested with characters that were not
           | affected. Sometimes reproducing bugs takes good luck more
           | than skill.
        
         | kkoncevicius wrote:
         | Yes I came to post exactly this, and found your comment, so
         | will reply instead. The bug doesn't seem to be obscure. It is
         | there in the right place. Someone thinking about checking "why
         | some players are attacked more often?" would probably choose
         | this as the first place to double check, since it is directly
         | related to selecting the player for attack.
         | 
         | Maybe the most occult part of this is figuring out that the
         | unique IDs assigned to the players play a role.
        
         | Strilanc wrote:
         | I would speculate the main hurdle was probably _believing the
         | players in the first place_. Humans are notoriously bad at not-
         | noticing-patterns in properly random data. And statistical bugs
         | like this require more effort and careful attention to detail
         | to reproduce than deterministic bugs.
         | 
         | Another hurdle is likely that game developer culture strongly
         | favors integration testing over unit testing. Games are
         | optimized for fun, not correctness, and you can't unit test
         | fun. This specific roulette selection function would have been
         | straightforward to unit test, and a unit test would have caught
         | the distortion. But now imagine people keep varying how
         | important distance is to the calculation in order to make it
         | "feel right". Updating those unit tests is suddenly a
         | noticeable slowdown on how quickly you can iterate on game
         | feel.
        
         | Normal_gaussian wrote:
         | Systematic debugging flaws probably; and lack of tooling to
         | easily isolate.
         | 
         | Systematic flaws: a cross between groupthink, early flawed
         | assumptions, deference to team leads, a 'I just look for 1hr,
         | if I can't find move on' (which leads to not looking), or just
         | plain simple "reading" instead of searching.
         | 
         | Lack of tooling: many game engines are infamous for lack of
         | control over tooling. I havent used many, but I understand it
         | would be quite an effort to run meaningful parameterised or
         | structured fuzz testing on most systems. This makes it hard to
         | artificially confirm suggestions. That said, there is
         | practically no excuse for them not to just add a bunch of
         | counters to the game - even on their internal testers it would
         | very quickly become clear there was a bias.
         | 
         | Most of my 'should have caught it earlier bugs' are of the
         | 'deference to lead' variety. I looked, didn't see immediately,
         | handed off with some notes, and then the follow up debugger(s)
         | took notes or thoughts as gospel. This is really hard to fight
         | - I write something along the lines of "my hunch is there is a
         | problem in code x because it handles y and is poorly
         | structured/tested. I checked z and found i, j - queries as
         | follows" and then find the debuggers effevtively refuse to look
         | anywhere past x. This is particularly true for a group of
         | debuggers, who play chinese whispers with groupthink and invent
         | reasons it must be x.
        
       | [deleted]
        
       | EarthLaunch wrote:
       | Why does weighted randomness seem so difficult for games? Are
       | there any libraries that simplify this? I couldn't find any for
       | JS.
       | 
       | So I created my own "algorithms" for things like randomly
       | choosing which type of plants spawn in the world. It weighs them
       | by the local frequency of each land-type. Eg if there's more
       | swamp nearby, it's more likely to spawn cattails.
       | 
       | It's awful. Not intuitive. Weights have to be passed in ordered
       | smallest to largest. Posting in hopes someone will correct my
       | entire approach or point out an industry-standard way of doing
       | these things.                 Utils.weightedRandom(percents,
       | types)            function weightedRandom(weight, outcomes){
       | var randNumber = Math.floor(Math.random()*100)         for(let
       | i=0; i<weight.length; i++){           if(randNumber<weight[i]){
       | return outcomes[i]           }           else {
       | randNumber -= weight[i]           }         }       }
        
         | shadowgovt wrote:
         | Statistics is actually pretty hard to get right, and it is the
         | nature of the problem space that errors aren't immediately
         | apparent unless one actually runs analytical regression on the
         | algorithm to confirm it has the right "shape," which (a) can be
         | time-consuming given the complexity of the algorithm and (b)
         | doesn't tend to be part of unit tests because unit test
         | doctrine is pathologically opposed to nondeterminism.
         | 
         | (This last pert is not an unsolvable problem, and in fact
         | random algorithms _should_ be unit tested. But it requires the
         | right kind of unit testing).
        
           | nmca wrote:
           | On occasion I have written a seeded large n statistical test
           | that passes & the submitted with the seed fixed. I think this
           | is the soundest approach, although it has a "your random
           | number is 7" feel to it.
        
         | [deleted]
        
         | jefftk wrote:
         | In Python:                   random.choices(population=['A',
         | 'B', 'C', 'D'],                        weights=[3, 2, 5, 7])
         | 
         | https://docs.python.org/3/library/random.html#random.choices
        
           | EarthLaunch wrote:
           | Thank you very much! That led me to a JS clone[0].
           | 
           | Python has amazing math libraries. I use numjs[1] for
           | everything, which is a port of numpy. I frequently wish I had
           | use of Python's libraries.
           | 
           | 0: https://github.com/parmentf/random-weighted-choice
           | 
           | 1: https://github.com/nicolaspanel/numjs
        
         | dekhn wrote:
         | IIRC the other solution is to make a tree structure instead of
         | a CDF. Can't remember if it's a good solution though.
        
         | freitzkriesler2 wrote:
         | I've been pondering a way to implement a quantum random number
         | generator into a game. Could this be useful at all?
        
         | arduinomancer wrote:
         | https://leetcode.com/problems/random-pick-with-weight/
        
         | rcme wrote:
         | In your example, the weights need to add up to 100 to work
         | correctly, right? The issue with the code in the article is
         | that the weights did not add up to 1.
        
         | ryani wrote:
         | Here's the standard algorithm for this problem
         | function weightedRandom(weight, outcomes){           var total
         | = sum( weight );           var roll = Math.random()*total; //
         | value in the range [0,total)           var seen = 0;
         | for(let i=0; i<weight.length; i++) {             seen +=
         | weight[i];             if(roll<seen)               return
         | outcomes[i];           }         }
        
       | theptip wrote:
       | It seems quite uncommon to write the statistical unit test for
       | this sort of algorithm; I suppose most languages lacking
       | statistical programming toolchain makes it less appealing.
       | 
       | I wonder if there's a cheap Frankenstein approach to create a
       | test-only interface into your code with a CLI / FFI and wrap it
       | with some Python to easily test the result distributions.
       | 
       | Then you can use tools like scipy or newer probabilistic
       | programming frameworks like pyro. Not sure what the FFI story is
       | in R, maybe something similar could be done there.
        
       | [deleted]
        
       ___________________________________________________________________
       (page generated 2023-02-10 23:00 UTC)