[HN Gopher] Aztec monks with 1/55 HP no longer die when picking ...
___________________________________________________________________
Aztec monks with 1/55 HP no longer die when picking up or dropping
a relic
Author : danso
Score : 473 points
Date : 2023-04-12 13:48 UTC (3 days ago)
(HTM) web link (www.reddit.com)
(TXT) w3m dump (www.reddit.com)
| elnatro wrote:
| Is Age of Empires playable in MacOS? I'd like to remember my
| childhood years but going back to windows after 15 years of
| Ubuntu and MacOS gives me headaches.
| userbinator wrote:
| My metrication extension turned the title into "Aztec monks with
| _13.37 W_ no longer die when picking up or dropping a relic ".
| Taywee wrote:
| That's not a lot of power for a monk. What's the typical monk's
| TDP?
| celeritascelery wrote:
| I don't understand why they didn't just use an integer. You can't
| have half a HP in AoE and nothing has HP so high that it would
| overflow a 32 bit integer. Seems like it would avoid a lot of
| problems.
| mqus wrote:
| Afaiu there are compounding factors like _1.5 here and 1.5
| there should result in_ 2.25 and so on
| adameasterling wrote:
| I had a really fascinating conversation with the lead architect
| at Frost Giant the other day. They're making the next
| StarCraft, basically.
|
| They don't use floating points.
|
| He didn't mention (IIRC) the possibility of rounding bugs; the
| reason he cited was something a bit more interesting: Floating
| points are not deterministic, which makes multiplayer
| challenging, as they simulate game state on each client's
| computers and only send commands across the wire.
|
| One wonders if the "out of sync" errors that plagued Age of
| Empires in my youth were partially explained by FP determinism
| issues!
| vippy wrote:
| ok, but who but TheViper or DauT has this issue? tth_tth (As a
| Japanese main, nerf Aztecs.)
| arendtio wrote:
| The T-West video talks about a match between Mr. Yo and Valas
| ;-)
| moneywoes wrote:
| Wow this comment had me reminiscing of watching AocZone
| tournaments replays of them in my youth
|
| Sigh
| spaceman_2020 wrote:
| Always a little surreal to see the Viper still around. He
| used to be a legend in the forums 20 years back.
| Sniffnoy wrote:
| Rather than linking to this Reddit thread, wouldn't it make more
| sense to either link to:
|
| * The linked-to patch notes?
| https://www.ageofempires.com/news/age-of-empires-ii-definiti...
|
| * The particular comment explaining this bug fix?
| https://old.reddit.com/r/Games/comments/12jbb9d/age_of_empir...
| danso wrote:
| I tried to and thought I had linked to the comment. I did
| wonder if the link went only to the thread, but the Reddit
| mobile web interface is so broken that I couldn't tell where
| the link was going to, though I figured the Aztec monk bug
| would stay at the top either way so people would figure it out.
|
| (the official patch notes don't explain the bug)
| raldi wrote:
| I would consider banning implicit casting of floats to ints from
| the codebase: Nobody would have intentionally truncated in this
| HP conversion; they would've rounded.
| tourgen wrote:
| [dead]
| einpoklum wrote:
| It's an unfortunate consequence of compatibility with C.
|
| I'm pretty sure you could get the compiler to warn you about
| this stuff though.
| Reason077 wrote:
| It's great that Microsoft are still actively maintaining a ~24
| year old game!
|
| Blizzard ought to take note. A few years back they announced
| "Warcraft 3 reforged" with great fanfare: a remastered version of
| the classic Warcraft 3, updated for modern systems with improved
| graphics etc. It looked/sounded fantastic!
|
| But despite it being a paid upgrade, what they released was a
| buggy mess that did little justice to the classic original. Then
| they immediately abandoned it and have released no updates or
| fixes since.
| roflyear wrote:
| Broodwar is still super popular and they don't do shit there
| either.
| hannofcart wrote:
| Even more amazing still is that it still has a large active
| player base and YouTube streamers make money playing it and
| casting videos of their play through. I'm routinely shocked by
| how easily I can join online multiplayer matches.
|
| For a 24 year old game!
|
| A bunch of guys in my company play it. Most of them were 3 or 4
| years when the game was released. A couple of them weren't even
| born.
|
| Real kudos to the team maintaining it. They constantly listen
| to player feedback and keep updating the various unit stats and
| bonuses to keep the game balanced.
| potemkinhr wrote:
| It's actually worse, they pulled the legacy version from the
| users and forced the (effectively) downgraded version to
| everyone. Even the owners of the legacy version were shafted as
| they forced a update which removed much of the functionality of
| the legacy version. To this date still the best version was the
| pre-patch one for everyone who has the original installers and
| the latest pre-upgrade patch
| Reason077 wrote:
| _Update:_ In fairness to Blizzard, I did just check this
| again and it seems like they have started maintaining
| Warcraft 3 Reforged again, releasing some small patches last
| year and a significant update in January 2023:
|
| https://news.blizzard.com/en-
| gb/warcraft3/23896791/warcraft-...
|
| I'll have to take another look now that this has been
| released.
|
| But still, there was a 2 year stretch between 2020 and 2022
| when the game was in a very crappy state and absolutely
| nothing was done to improve it or address the issues.
| vultour wrote:
| Blizzard also pulled the original W3 downloads and switched
| everyone to a non-hd version of Reforged. I'm still mad
| about that because I paid for both and I'm no longer able
| to get one of them.
| LeoNatan25 wrote:
| But isn't Reforged using the same engine as the original,
| with higher res assets (mostly textures)? At least, I
| thought so, as that was part of the criticism of
| Reforged.
| Reason077 wrote:
| Nothing wrong with that, necessarily. In fact, I'd argue
| that's exactly what I would want out of an ideal War3
| reforged. Exactly the same game modernised for modern
| systems, with the "same" graphics just at higher
| resolution and detail.
|
| Besides, World of Warcraft, StarCraft 2, and Heroes of
| the Storm were all built using upgraded versions of the
| Warcraft 3 engine, so it's proven to be quite capable.
| It's logical to use an updated version of the engine for
| an updated version of the same game.
|
| Trying who port the game to an entirely different engine
| would not only be much more effort, it would risk
| introducing subtle differences in gameplay and feel that
| could mean it doesn't play quite the same any more.
| Razengan wrote:
| This kind of crap is actually why I will not buy Diablo 4
| (even though I kinda want to, to have a good hack'n'slash on
| my PS5) or put money into any Blizzard game anymore.
| zelphirkalt wrote:
| And the AoE2 DE has way higher system requirements while only
| looking marginally better in some aspects, but looks worse
| than 2 decades old 2d art in some other aspects. Just because
| it "has to be 3D" these days, while there is nothing truly
| requiring any 3D in the game.
|
| This is subjective, but I liked some of the old unit designs
| more than the new ones. For example Teutonic Knights and
| Cataphracts looked better in my opinion. The Teutonic Knight
| looked leaner and taller, while it now looks a bit like a
| walking barrel. OK, somewhere they need to carry all that
| armor ... but still I liked the old ones better.
|
| Also I would have been completely fine with units having only
| 8 or whatever directions in which they can look. I don't need
| 360deg all-around rendering of units. It even substracts a
| little from AoE2's abstract character.
|
| What I do like is, that they added more civs.
| VoodooJuJu wrote:
| I think DE actually looks worse. Old graphics hold up great
| - just look at this: https://imgur.com/hWSZBpb. The new
| ones lost the soul. They have a weird glow/fuzziness.
| Nonetheless, DE has better multiplayer performance and cool
| new civs, so it's the one I play.
| qwytw wrote:
| > I don't need 360deg all-around rendering of unit
|
| But you don't have it anyway? I assumed the game is still
| actually isometric and not 3d but even if it is the camera
| is still fixed.
| Laaas wrote:
| I'm surprised this isn't illegal.
| maeil wrote:
| I would imagine that in certain countries with strong
| consumer rights (e.g. Australia or Germany) it may well be,
| just understandably no one bothers with the expensive legal
| fight it would take.
| tetha wrote:
| Yeah it appears my Diablo 2 has been pulled from my Blizzard
| account when the D2 Remastered was launched, at least I can't
| find it anymore. And now I either have to dig up the CD and key
| and hope those still work or pay $60 or something to play D2.
| My desire isn't really that big.
| alewi481 wrote:
| I see this link on the Blizzard support site that provides
| downloads to classic D2 and LoD but I haven't tested them out
| to see if they ask for a CD key or not.
|
| https://us.battle.net/support/en/article/13867
| yen223 wrote:
| It's not just maintenance, Microsoft has released several
| expansion packs to the original Age of Empires II, plus an Xbox
| port to boot.
| spaceman_2020 wrote:
| The amazing thing is that this new version of AoE was a fan
| made upgrade, and they did such a good job that MS brought them
| in house.
|
| The Forgotten Empires team is brilliant and I can't be more
| grateful to them for bringing back a childhood favorite.
| mcraiha wrote:
| From the comments:
|
| "This was caused by a floating point rounding error. A unit
| switching jobs internally becomes a different unit (i.e. a monk
| with a relic becomes a monk without a relic), and when doing
| that, HP is scaled proportionally based on the old and new max HP
| using 32-bit floating point maths."
|
| And there are YouTube videos about this
| https://www.youtube.com/watch?v=MytWNbpnAVY
| intrasight wrote:
| I woke up in the middle of the night and of course opened up
| HN. This was near the top and was an interesting read.
|
| I told my GF that last night I had insomnia and found myself
| researching why Aztec monks die when picking up a relic, and
| that doing so resulted in plumbing the depths of an important
| computer science topic.
|
| She said "Sounds like you were reading Hacker News". She knows
| me so well now :)
| ReactiveJelly wrote:
| > The formula was probably `return new_maxhp * (old_hp /
| old_maxhp);` ...
|
| > Due to floating point rounding errors, convert_hp(1, 55, 55)
| equals 0.999999940395355224609375, which is less than 1, which
| means the unit dies.
|
| Ahh. The old "Multiplying and dividing is associative... for
| the set of reals, not for the subset that you can actually
| afford to compute with." So it should have been `(new_maxhp *
| old_hp) / old_maxhp`. ffmpeg has a whole AVRational class for
| the same type of problem when converting timestamps accurately
| between 2 timebases.
|
| Reminds me of the TF2 ammo boxes that give 40 metal on Linux
| and 41 on Windows
| https://www.youtube.com/watch?v=QzZoo1yAQag&pp=ygUfdGYyIGhlY...
|
| Apparently the compiler used on Linux chose a less-accurate
| multiply instruction for 0.2 * 200.
|
| Two wrongs make a right - After being less accurate but
| rounding up where you don't need to, the Linux binary correctly
| arrives at 40, and the Windows binary arrives at 41.
|
| For percents (and dollars) I always do everything in cents and
| divide by 100 at the very end. "20 * 200 / 100" can be done
| with pure ints, and f32 can represent i16 exactly.
| zelphirkalt wrote:
| Seems all that could have been avoided by using rationals in
| general and the condition for living being >0 instead of
| dying <1. Not sure in what case it makes sense to have dying
| at smaller than 1. To the user all the numbers are integers,
| so why not use rationals instead of floats?
|
| The more I write code, the more I notice how rarely one truly
| should want floats in most kinds of programs and how they
| almost always carry a whole bag of problems with them.
| avgcorrection wrote:
| > Seems all that could have been avoided by using rationals
| in general
|
| Why can't they store HP internally as "millihealth"
| integers, do integer arithmetic (including division), and
| then divide that by 1000 purely for display?
| firstlink wrote:
| This would require competent senior programmers who are
| way too expensive, and anyways once hired are used for
| bullshit tasks like project management.
| tialaramex wrote:
| The trouble you have is that you really wanted _reals_ and
| the _rationals_ are not a much better substitute than the
| _floats_ (which are mostly just one particularly
| specialised flavour of rational)
|
| It doesn't feel immediately like there ought to be a
| problem, but witness, mathematically _almost all of the
| reals are Normal_ and unfortunately Normal doesn 't mean
| "normal" it's a technical mathematical word, that for our
| purposes means roughly "completely batshit".
|
| Normal numbers are non-computable, so we definitely don't
| want to try to use them in software, which is a problem
| because again, _almost all of the reals are Normal_.
| l__l wrote:
| Huh? This isn't making a lot of sense to me. Why do you
| say the rationals aren't much better then floats? In
| situations like this surely we absolutely want to be
| working in the rationals, and they're a very easy way to
| do these calculations correctly without having to worry
| about tolerance bounds for arbitrary-precision float
| calculations
| hgsgm wrote:
| Algebraics plus pi avoid almost all the concern you
| mention, but still have the same problem for software.
| All those nasty reals are _unreachable_ by your program.
|
| The actual problems with irrationals is that it is
| extremely hard to measure their size without converting
| to rational approximation, so you are back to the
| original problem.
| CodesInChaos wrote:
| The big problem with rationals is that it's easy to end up
| with both nominator and denominator growing without bounds,
| which IMO is an even bigger pitfall than those of floating-
| point or fixed-point.
| fendy3002 wrote:
| In terms of hp without decimal in gaming and related with
| max hp changing, the best solution should be to rounding
| down (or nearest zero rounding) the result, and keep
| minimum hp to 1 when max hp changes. In case for minimum hp
| unit (1 in this case) to have changed into lower max hp
| then they'll die too, hence why minimum 1 hp as the result
| is logical.
|
| This is exactly why heroes won't die in Dota2 when toggling
| off armlet while having 1 hp
| ilyt wrote:
| > Not sure in what case it makes sense to have dying at
| smaller than 1. To the user all the numbers are integers,
| so why not use rationals instead of floats?
|
| If killing unit takes X attacks, user buys 10% attack
| damage upgrade, and it still takes X attacks they will be
| annoyed. If rounding down takes that to x-1 attacks it
| might be preferable.
|
| That being said you're absolutely right. just use HP*100 in
| calculations and display HP/100 to the user, and when you
| need to round into specific direction do it explicitly
| DaiPlusPlus wrote:
| > Seems all that could have been avoided by using rationals
| in general
|
| It's 2023: I'm still surprised that so many new
| languages/platforms still only provide only basic integer
| and IEEE-754 types for numerics: Rust, C#, Java, Swift and
| others still lack built-in, runtime-provided, nor even
| standard-library-provided rational types, which I assume
| really _should_ be the preferred type for most business
| /domain/application values, exactly for things like RTS
| game unit health, for example. (and Java's lack of operator
| overloading makes this even more painful).
|
| ----
|
| On a related note, can we agree that an application-
| programming language today should also include signed-and-
| unsigned "money-safe" decimal types, and IEEE-754 types
| should be smarter about when NaN can happen - and it should
| support interval types (and evaluating interval-type-based
| contract invariants): this would eliminate whole classes of
| bugs in the first place (too many programmers think
| single/double is appropriate for storing currency values,
| ugh).
| jacquesm wrote:
| > can we agree that an application-programming language
| today should also include signed-and-unsigned "money-
| safe" decimal types
|
| You mean like COBOL?
| marcosdumay wrote:
| Yep, like COBOL, or SQL.
|
| But, in fact, I don't know of any language that doesn't.
| They are just not basic types.
| Kiro wrote:
| > and Java's lack of operator overloading makes this even
| more painful
|
| Why?
| bombolo wrote:
| Because you can't make your own types that work better.
| hgsgm wrote:
| Of course you can. You just can't use operators for them.
|
| Unless you go Haskell where anything can be an operator
| name, operators are just a minor convenience hack .
| bombolo wrote:
| So you can but you need to rewrite everything instead of
| just changing a type, and the code will look completely
| impossible to read.
| cwillu wrote:
| Some aspects of the problem, exagerated for effect:
| boolean isDead = (new I("0.9")).divide(new
| I("55")).multiply(new I("0.1")).lessThan(new I("1"))
| marcellus23 wrote:
| Foundation has the Decimal type (not technically part of
| the Swift standard lib, but in practice available for
| most uses of Swift).
| fisf wrote:
| Java pretty much provides BigDecimal for that
| pclmulqdq wrote:
| I'm increasingly convinced that peoples' problems with
| 754 types are psychological. With integers, they are very
| careful about order of operations, precision, rounding,
| etc. With doubles, the average programmer fires and
| forgets. Sometimes that has bad consequences.
|
| A decimal type is definitely necessary, and you can use
| IEEE decimal floating point for that, too! Other decimal
| types are very useful. Rationals are a different story:
| rational numbers are great for addition and subtraction,
| but if you're going to be doing a lot of multiplication
| and division, you are going to find yourself also doing a
| lot of slow gcd calculations to reduce/renormalize the
| fractions (incidentally, decimal types also need
| renormalization, but it's a lot cheaper). Most cases
| where rational types are used today are very careful
| about not having long chains of these operations.
|
| As to NaNs: those are all considered pretty carefully,
| and 754-2019 actually reduced the amount of NaNs that
| propagate around quite a bit. For example, make sure you
| are using fmax(a, b) instead of std::max<double>(a, b).
| Someone wrote:
| > It's 2023: I'm still surprised that so many new
| languages/platforms [...] still lack built-in, runtime-
| provided, nor even standard-library-provided rational
| types
|
| Because numerators and denominators can blow up easily,
| rational types effectively require storing them as
| bigints. That makes them bad from a performance
| viewpoint.
|
| Assuming your application will work fine with fixed-size
| rationals (which, IMO, is highly unlikely), the natural
| way to store rationals in fixed-size storage wastes lots
| of room.
|
| For example, in a _(int32 nominator, int32 denominator)_
| pair, there are about 232 ways to encode '1' that way,
| 231 to encode 1/2, etc. I also think such a fixed-size
| rational type isn't very natural to work with
|
| Rationals also require regularly computing a gcd when you
| add (1/3 + 1/6 isn't 9/18 but 1/2) or multiply (10/21 x
| 7/5 isn't 70/105 but 2/3) them, slowing down things more
| (you can use heuristics to avoid some of those
| simplifications, but not doing one when that's possible
| may mean your rationals keep huge numerators and
| denominators, slowing down operations)
| e12e wrote:
| > Because numerators and denominators can blow up easily,
| rational types effectively require storing them as
| bigints. That makes them bad from a performance
| viewpoint.
|
| While hardware support for full number towers might be
| neat, I don't think anyone is suggesting that int and
| floats should not have language/standard library support
| - only that there should be a blessed option for precise
| arithmetic.
|
| Usually the slow correct answer is preferable to the
| quick wrong answer (esp in business logic).
| kortex wrote:
| I'm (vaguely) surprised there hasn't been a hardware type
| for rationals. Then the GCD operation could be done in
| hardware and everything would be fast (at least as fast
| as floats). Not surprising, because adding new hardware
| data types is hard, but the financial institutions would
| benefit from something like that.
|
| A rat64 could be:
|
| - 1 sign bit
|
| - 3 format bits. Determines where the decimal is located,
| e.g. 30.30 vs 52.8.
|
| - 60 bits of numerator and denominator. The split is
| determined by the format bit. 50.10 would be handy for
| any percent/ppt operations (e.g. Most USD operations)
|
| Might need an error bit, but that's my 5 minute gist.
| Someone wrote:
| > Then the GCD operation could be done in hardware and
| everything would be fast (at least as fast as floats).
|
| Could it? Is there a fast way to do GCD in hardware?
|
| Googling gave me
| https://en.wikipedia.org/wiki/Binary_GCD_algorithm, which
| needs _O(log2(max(u, v)))_ operations to compute
| _gcd(u,v)_ , but I wouldn't know whether that's the best
| we can do in hardware, or whether that's 'as fast as
| floats'.
|
| Also, I don't see how your format describes a rational
| type. Rationals store numbers as _p /q_ for integer _p_
| and _q_ , not with a decimal point.
| kortex wrote:
| Sorry, abuse of notation. 30.30 would be 30 bits
| numerator, 30 bits denominator.
|
| I would imagine it would not need to fully reduce after
| every operation, there's probably tricks where if you
| know the factors going in, there will be obvious ones
| after multiplication/division.
|
| It's not my best idea :p
| justinpombrio wrote:
| > 60 bits of numerator and denominator.
|
| The trouble is this isn't enough, even for ordinary
| usage. The numerator and denominator _grow in proportion
| to the total number of operations you have performed_.
| For example, if you start with `1` and then multiply by
| `80 /81` a thousand times, you get a number that's around
| 1e-6, but when expressed as a rational the numerator and
| denominator have _hundreds_ of digits:
|
| https://www.wolframalpha.com/input?i=%2880%2F81%29%5E1000
| kortex wrote:
| But how often are people using decimal types to do that?
| Most of the uses I could see this type being used for -
| currency, percent scaling, datetimes, audio/video codec
| frame rates - all are basically fixed point operations.
| Anything involving powers of 80/81 would probably need
| bigint based rationals anyways.
|
| Actually if you had an int64 type which was scaled by
| flicks, that'd give you quite a lot of latitude for most
| day to day stuff.
|
| https://en.m.wikipedia.org/wiki/Flick_(time)
| justinpombrio wrote:
| Yeah, fixed point is different from rational, and all
| those examples you gave sound to me like fixed point. And
| that can be implemented efficiently without dedicated
| hardware support: the denominator is fixed, and you store
| the numerator as an integer.
|
| A 1/3 off discount on a $10 item is $6.67 (or $6.66 if
| rounding in the customer's favor), _not_ $10 /3.
|
| (Except datetime, did you mean timestamp? A timestamp is
| an instant in time, and it often makes sense to store it
| in high precision because you're saying exactly when
| something happened. A datetime is for communicating
| between humans who are using some particular calendar; it
| rarely makes sense to have more than minute precision.)
| carlmr wrote:
| >It's 2023: I'm still surprised that so many new
| languages/platforms still only provide only basic integer
| and IEEE-754 types for numerics: Rust, C#, Java, Swift
| and others still lack built-in, runtime-provided, nor
| even standard-library-provided rational types
|
| C# has the base-10 high accuracy decimal type:
| https://learn.microsoft.com/en-us/dotnet/csharp/language-
| ref...
| colejohnson66 wrote:
| There are two problems with the `decimal` type: it's not
| IEEE-754 compliant, and it is 16 bytes, which prevents
| atomic reads/writes (without locks).
|
| This is a problem in one of my company's applications, as
| we have a background thread doing work entirely with
| `decimal` objects, but providing a readout for the GUI
| necessitates a lock on every write (even if never read),
| and another for the read by the GUI. There's barely any
| overhead (nanoseconds worth), but the logic to work
| around it is a pain, and, if you forget to actually use a
| lock, good luck with that bug.
|
| .NET 8, however, will introduce[0][1] proper IEEE-754
| decimal float types, including `Decimal32` and
| `Decimal64` which will allow atomic reads/writes.
|
| [0]: https://github.com/dotnet/runtime/issues/81376
|
| [1]: https://github.com/dotnet/runtime/issues/79004
| bawolff wrote:
| > It's 2023
|
| This is a game originally from 1999. Although i doubt it
| would make a difference.
| ouid wrote:
| why would rationals be good for RTS.
|
| If all of your operations occur with some reasonable
| minimum denominator, just use ints. If not, that
| arithmetic is going to become unbounded really fast.
| PhilipRoman wrote:
| Aren't rationals subject to exponential blowup in
| storage/precision? IMO the best approach for business
| logic values is picking the smallest meaningful unit and
| representing it with integers. Precision and storage
| requirements become very easy to reason about.
| DaiPlusPlus wrote:
| > IMO the best approach for business logic values is
| picking the smallest meaningful unit and representing it
| with integers.
|
| How would you design an RTS unit stats system to avoid
| this AoE Monk HP bug using only integer types?
| CodesInChaos wrote:
| `(new_maxhp * old_hp) / old_maxhp` avoids the original
| problem when using integers. Though you still need to
| make sure your type is big enough to not overflow.
|
| Or using fixed-point (which are a relatively simple
| abstraction over integers): `old_hp * (new_maxhp *
| old_maxhp)`.
| rvnx wrote:
| They probably just added: return ROUND()... and went back
| to play
| ilyt wrote:
| max(1,...
| bruce343434 wrote:
| How much health precision do you need? Make hp an int. Or
| like a /64 fixed point.
| falcor84 wrote:
| Well, in this case, if a unit is converted to a different
| type and back, it would just keep its (absolute) value of
| HP (in this case 1), no need to scale anything.
| db48x wrote:
| You haven't thought it through yet. In this case, HP _is_
| an integer, and so is the MaxHP for the unit type. And
| yet the bug still occurs! Storing the HP as an integer
| does not prevent the problem from ever occurring, because
| fundamentally the user still expects HP to be
| proportional.
|
| That is, suppose a unit is sitting there at full health,
| and you research a tech that increases that unit's max
| hp? Should the unit now be at less than full health, as
| if it had been in combat? Users probably don't like that.
|
| Suppose it is at full health, and then it gets downgraded
| to a type with less maximum health. Does it stay at it's
| current HP? Users probably won't like being attacked with
| supercharged units that have extra HP; they'll think that
| the other player was cheating somehow.
|
| What if it is damaged and at half health, then gets
| upgraded. Should it be fully healed? Gain HP equal to the
| difference between the new and old maximum HP? Or should
| it gain half of that, so that it stays at half health?
|
| Or perhaps HP is too limiting, and the game should do
| what Dwarf Fortress does. DF knows the approximate
| surface area of every body part (based on each creature's
| body plan, plus individual stats such as strength,
| fatness, size, etc), and the size of every weapon. Every
| attack therefore deals damage to a certain area, measured
| in square inches, and individual body parts will be
| destroyed once a sufficient percentage of that surface
| area is damaged by wounds.
|
| Or maybe you are designing this game in the 90's, and you
| have to worry about squeezing unit updates for 200 units
| per player into the bandwidth provided by the average
| modem of the day (probably 28.8kbaud), so you stick to
| one integer because it's the simplest think that can
| possibly work, and the number of bytes per update can be
| calculated in advance. And then some other schmuck gets
| stuck with the job of handling unit type changes (but be
| warned that the schmuck might be yourself in six months).
| ilyt wrote:
| >That is, suppose a unit is sitting there at full health,
| and you research a tech that increases that unit's max
| hp? Should the unit now be at less than full health, as
| if it had been in combat? Users probably don't like that.
|
| >Suppose it is at full health, and then it gets
| downgraded to a type with less maximum health. Does it
| stay at it's current HP? Users probably won't like being
| attacked with supercharged units that have extra HP;
| they'll think that the other player was cheating somehow.
|
| >What if it is damaged and at half health, then gets
| upgraded. Should it be fully healed? Gain HP equal to the
| difference between the new and old maximum HP? Or should
| it gain half of that, so that it stays at half health?
| if (oldHP == maxOldHP) { newHP = newMaxHP } else
| { newHP = max(1,scale(oldHP,oldMaxHP,newMaxHP))
|
| not exactly complex
| ghusbands wrote:
| Sure, if you fully predict all bugs in advance and
| compensate for them, nothing is complex, but that's not
| really feasible.
| db48x wrote:
| Not exactly complex, but you posted too quickly to have
| found the best solution.
|
| A better solution is to kill the unit when it drops below
| zero HP, not when it drops below 1.0; scaling will never
| move the current HP past zero in either direction. Having
| 0.9999994 HP instead of 1.0 HP would not cause any
| problems then; the unit is still one hit away from death
| in either case.
|
| The best solution is probably to store the current HP as
| a percentage of the max, because then you never have to
| rescale it in the first place.
| InitialLastName wrote:
| > The best solution is probably to store the current HP
| as a percentage of the max, because then you never have
| to rescale it in the first place.
|
| Doesn't this solution make the more common calculations
| more expensive, complicated, and error-prone to make one
| rare calculation easier? It seems like far more of the
| operations on the unit's current HP will be "gets damaged
| by X hp" or "gets healed by X hp", both of which would
| require the equivalent of the above conversion to
| establish a result.
| db48x wrote:
| If you've changed HP to a percentage, why wouldn't you
| also change the damage and other related numbers (such as
| damage reduction and so on) to percentages as well?
| Nobody would be dumb enough to store them in different
| units and then convert every time they manipulate them.
| mlyle wrote:
| > why wouldn't you also change the damage and other
| related numbers (such as damage reduction and so on) to
| percentages as well?
|
| Because a sword might do 5HP of damage, not 10% of
| anyone's damage (whether they've got 50 or 5000HP).
| Otherwise, hit points are meaningless: 10 attacks with a
| 10%-damage weapon kills a lowly serf or a mighty dragon.
|
| And because damage reduction might reduce a fixed amount
| of damage from an attack. Etc.
| db48x wrote:
| Obviously a dragon doesn't get damaged at all by a puny
| little sword. You can't just say that hitting a dragon
| with a sword a thousand times would kill it, when none of
| the attacks can get through the dragon's armored hide. On
| the other hand, it will die immediately if pierced by an
| arrow provided that arrow hits the one spot where the
| hide is missing a scale. The dragon has 100% DR, except
| in that one spot.
| mlyle wrote:
| > A better solution is to kill the unit when it drops
| below zero HP
|
| Then you have the situation where units are displayed as
| having 0 HP but are still alive.
| db48x wrote:
| So what? The players already know that attacks deal
| fractional HP damage.
| mlyle wrote:
| > The players already know that attacks deal fractional
| HP damage.
|
| Top-end players who analyze the engine enough do.
|
| Otherwise, they shrug and say "sometimes 1, sometimes 2
| HP"
|
| And even so, we're used to seeing 0/50HP and it meaning
| "dead" across many games. Seeing 0/50HP and it meaning
| "just a small amount of HP left" isn't ideal.
|
| Not to mention that weird situations with
| 5.551115123125783e-17 HP remaining aren't great either
| (where a player may end up with effectively an "extra"
| hit point).
| db48x wrote:
| Again I say "so what?". The unit is one hit away from
| death either way, and the player will know it.
| mlyle wrote:
| At this point, with your Smaug-related comment, etc--
| I've become convinced you're trolling.
|
| But just to humor you: the desire is to have a system
| where floating point neither surprisingly kills nor gives
| characters extra hit points. There's a lot of subtlety in
| this. Schemes where all damage are percents don't
| preserve the essential pieces of RPG combat systems.
| Moving the threshold from 1 to 0 HP violates the
| conventions of the art and doesn't eliminate the problems
| (you can still end up with hit points epsilon away from
| 0, instead of 1).
| rini17 wrote:
| Did this exponential blowup ever prove troublesome in
| practice? I think it can be easily solved by
| strategically placed rounding steps. But explicit
| rounding is advisable in many cases anyway.
| jrochkind1 wrote:
| But strategically placed rounding was in fact the
| solution to the original problem that in this thread
| Rationals were proposed as solving...
|
| Rational types are not super popular and don't get used
| that much, most (not all) people that end up using them
| do it very intentionally and consciously and know what
| they're dealing with -- if they were more ubiquitious, I
| suspect more trouble would be seen "in practice".
|
| While it's probably true that any digital number format
| will have edge cases that in fact come up in practice, my
| personal choice of "Why the heck isn't this more popular,
| why doesn't every language support it, why isn't it in
| fact the default representation of a numeric literal" --
| is floating point "decimal" types, like ruby (or I think
| Java?) BigDecimal, rather than rational. I think they
| mostly work matching programmer's mental models of
| numbers, and for many/most common uses on 2023 platforms
| the performance is just fine. (this would not have been
| true 30 years ago).
| rini17 wrote:
| Or it's vendors that don't care about correctness, like
| providing decimals by default and high performance
| floating point as an "optimized" option. Python did
| something like that by using bigints as a default for
| integers.
|
| What would not have been true 30 years ago? I remember
| "real" fixed-point type built-in in Turbo Pascal and
| explicitly documented as suitable for money. Common Lisp
| has had first class fractions support since the start.
| jrochkind1 wrote:
| I meant to suggest that 30 years ago the performance
| difference between "floats" (floating-point binary) and
| "BigDecimal"-style arbitrary-precision floating-point
| decimal would have been much more significant to many
| more real-world use cases, compared to now. So that may
| have been a reason not to make them the _default_ when
| you simply write a literal `5.4` in code, but that
| argument is less now.
| GreymanTheGrey wrote:
| Slight correction, from a former Turbo Pascal (and
| subsequent Delphi) programmer...
|
| "Real" types were platform-dependent floating-point
| types, not suitable for monetary calculations whatsoever.
| and would map to either Single or Double depending on the
| underlying CPU architecture. Sort of like a C-style "int"
| that would map to an 8-bit, 16-bit, 24-bit, 32-bit,
| 36-bit, 60-bit, 64-bit etc integer, depending on the
| compiler and the compile target.
|
| Turbo Pascal did have an 8-byte, fixed point, "Currency"
| type suitable for monetary calculations, however using it
| was very, very slow compared to pure floating point ops -
| just as the comment you replied to suggested. If that
| weren't enough, library support (both built-in and 3rd-
| party) for math and other utility functions was either
| limited or non-existent.
| fm77 wrote:
| Slight correction from an Turbo Pascal expert ;-)
|
| Turbo Pascal did NOT have an 8-byte fixed point
| "currency" type suitable for monetary calculations. It
| did have an int64 type called "comp" though which was
| handled as a float by the FPU and hence not slower than
| the types "single" (f32), "double" (f64) or "extended"
| (f80).
|
| IIRC, "currency" came with Delphi V2.0 (or even later),
| but then still it wasn't slower than other floats when
| you did heavy calculations with it as it was also handled
| by the FPU. Only reads and writes from and to such
| variables were expensive as there was always a scaling
| (multiplication by 1e4 and 1e-4) involved -- internally
| it was that int64 "comp" type. (But here I might be
| wrong, I never used "currency" and my Delphi knowledge is
| quite fuzzy).
| MobiusHorizons wrote:
| Fun fact many processors actually support decimal types
| in hardware. I believe you can use them in c with
| _Decimal. Worked on my Ryzen 3700x and (if memory serves)
| my M1 mac
| samtho wrote:
| > On a related note, can we agree that an application-
| programming language today should also include signed-
| and-unsigned "money-safe" decimal types
|
| I'm willing to bet that this has to do with how we
| historically have handled monetary values which is
| storing and computing it in the respective currency's
| fractional unit. The advantage is that you can still do
| math operations directly on this value (as opposed to an
| object that contains it) and at most you'll be off by, in
| the case of the US dollar, one cent. Because we cannot
| represent fractional units of the already smallest unit
| of currency, we have to choose a value anyway to charge
| or dispense. Unlike, say, if we stored it in dollars as a
| floating point and we can start compounding errors from
| the floating point type.
|
| What interesting is that pre computers, we didn't even
| treat currency values as an real decimal (for base 10
| currencies) and the decimal point was simply a convenient
| way to store partial values. I note this because you
| don't see old ledgers where they store more than 2
| decimal places, therefore IMO, this was just an integer
| in disguise all along.
|
| Old habits die hard?
| hermitdev wrote:
| > Because we cannot represent fractional units of the
| already smallest unit of currency, we have to choose a
| value anyway to charge or dispense. Unlike, say, if we
| stored it in dollars as a floating point and we can start
| compounding errors from the floating point type.
|
| I've spent 20 years mostly working in finance. You'd be
| surprised at the prevalence of floating points used to
| represent currency. I cringe every time I see it, but
| it's surprisingly common (and wrong).
|
| More correctly, pricing of securities (from exchanges) is
| done with integers and a scaling factor. The factor is
| typically static and doesn't need to be transmitted on
| every tick. The factor tells you effectively how many
| fractional digits are present (e.g. the actual price is
| multiplied by 10^-factor). Factors of 4 or even 6 are
| somewhat common, but some securities have to go with less
| precision. I remember in particular Berkshire Hathaway
| causing issues with overflow using 32-bit ints in the
| last decade (because they never split their shares, the
| share price is quite large).
| wruza wrote:
| _You 'd be surprised at the prevalence of floating points
| used to represent currency. I cringe every time_
|
| We all cringe but then there's a "floating point or gtfo"
| ultimatum that most languages present to you. People
| would be happy to not use FP. But the reality is, you can
| have a monetary column in a 30 years old database engine,
| but not in a 5 years old language runtime. When you only
| have a hammer...
| wruza wrote:
| Tbh, the only practical non-integers we all need (apart
| from science-ish pretence and graphics) are .00, .000,
| .0000 and .000000 decimals (money, qty, percent.00,
| milliqty). Literally all business and in-game accounting
| needs get covered by these. Even edge/rounding issues are
| irrelevant, because everyone is ready to just agree to
| either way of doing it, and that agreement is much more
| important than the method itself. This floating bullshit is
| basically of none, zero, nil practical use outside of
| academics.
|
| Modern CPUs can effectively emulate whole subroutines in
| microcode, but somehow we got stuck with that useless
| binary floating point standard for numbers. And on top of
| that, languages provide them as a default numeric system
| for all new software.
| gabereiser wrote:
| bool is_alive(const Entity* unit) { return unit->hp
| > ZERO_FLOAT; }
|
| Super easy...
|
| Likewise I'm with you, the more I code, the more I see
| these kinds of things as bad design choices. If you're
| going to deal with a type, keep it that type. If you're
| going to convert, you need to take care of edge cases like
| OP. And don't just add 0.0001f; that's an exploit waiting
| to happen by someone with a macro to pickup/drop relics.
| perihelions wrote:
| Rationals fail in their own spectacular ways. Take a simple
| approximate exponential decay: x - (99/100) * x. In exact
| rational arithmetic, your program will happily calculate
| integers (99^k) and (100^k) for unboundedly large values of
| _k_ (there 's no reduction - they're all coprime), grinding
| the program to a halt until it runs out of memory.
|
| "Oh, the solution is obvious: you should simply round that
| to an approximate fraction..." -- yes, and that's floating-
| point arithmetic. Point is, you can't use either with
| thinking, about numerical representations and their
| possible failure modes.
| zelphirkalt wrote:
| The difference is, that with rationals you do not lose
| any precision on the way. I doubt, that 99^k is part of
| AoE2 code. For the simple calculations in AoE2 regarding
| unit health, rationals will do a fine job. With rationals
| the rounding does not happen during the precise
| calculation. It happens explicitly, only once, at the end
| of the calculation, at the programmer's wish and
| conscious decision, thereby avoiding the kind of issue we
| see here.
|
| Rationals might not be the solve all problems type, but
| here they seem very applicable.
| perihelions wrote:
| It's a very common pattern, in its more general forms.
| Sure, you can abstract away the naive re-implementation
| of exp() loop { x - a*x }
|
| as one function call x(t) = exp(-k*t), so that one looks
| pointless. But moving-average [0] type expressions
| loop { x - a*x + f(t) }
|
| are more interesting. You can't generally refactor those
| into exp() calls, like x(t) = sum[ f(t_i) * exp(-k*(t -
| t_i)) ], since that introduces a memory leak - you need
| to hold an explicit list of all the past values of f(t),
| in order to compute it this way. That's why the pattern
| [0] is uniquely useful: it's a trick to incrementally
| accumulate a moving average using just one variable of
| state.
|
| [0] https://en.wikipedia.org/wiki/Moving_average#Exponent
| ial_mov...
|
| Here's one uncontrived way this pattern might show up:
| "the NPC has a numeric disposition towards the player,
| and the player's actions have positive and negative
| effects on it. These effects have _finite_ duration, and
| disposition _decays_ back to the neutral value ". Another
| way: you have a large list (like a time series) you want
| to reduce to a small one by interpolation. Another way:
| you have some PID-like controller in your program, and to
| make it behave, you need a cheap filter to clean a
| jittery input signal. (I'm building these for my Factorio
| factories right now - it's the only reason this example
| occurred to me. "x - (99/100) * x" is a factory control
| component I had to implement out of int32_t's).
| hinkley wrote:
| In a simulation nobody is calculating n x m^k. They're
| calculating n X m in k loops spread over k ticks. And
| given that fact, if you round or truncate at the end of
| each cycle, as one often does with game points (eg, fire
| resistance in D&D), then there is no problem.
|
| For money systems, we also tend to round on every step to
| the nearest penny.
|
| What you don't have with rationals is the problem of
| 10.00 - 4.10 + 3.20 ending in a 9.
| still_grokking wrote:
| > The more I write code, the more I notice how rarely one
| truly should want floats in most kinds of programs and how
| they almost always carry a whole bag of problems with them.
|
| This! Imho you more or less _never_ want floats under
| "normal" conditions.
|
| Also in most application domains it makes exactly no
| difference that floats have HW support, as the bottlenecks
| are there usually elsewhere. And in case you really need
| real fast floating point math (say for simulations) you
| would do it anyway on the GPU nowadays.
|
| The only langue I know of that is sane in this regard is
| Pyret:
|
| https://www.pyret.org/
|
| [CTRL-F: Pyret has numbers]
|
| I'm still baffled no other new language thought about
| something so basic like number ever again. Everybody is
| just using what the HW provides natively since the year of
| yore. As a result there is no motivation for HW vendors to
| update the status quo form the state of the art of the 60's
| of the last century. Imho having support for rationals and
| (fixpoint) decimal numbers in std. hardware is long
| overdue! But it would only happen if there would be serous
| demand form the runtime / language vendors. Classical
| chicken egg problem.
| marcosdumay wrote:
| Floats are a computer representation of scientific
| notation, used for scientific computation.
| Coincidentally, hardware support is extremely important
| for scientific computation. (A bit less now than in the
| 90's but still a showstopper.)
|
| Hardware support is also extremely important for games,
| but floats are not a good representation for most of it.
| IMO, game data should be composed exclusively of integral
| numbers, but it is natural to want a little bit more of
| precision some times.
| still_grokking wrote:
| > Floats are a computer representation of scientific
| notation
|
| No, they aren't. They are IEEE 754 binary floating point
| data. Something extremely weird, without precedent
| outside of computers science.
|
| > Coincidentally, hardware support is extremely important
| for scientific computation.
|
| Maybe it was once, but today it isn't.
|
| If you need to do any serious number crunching you use
| nowadays dedicated hardware for that (which isn't part of
| the main CPU usually). (You could use CPU integrated GPUs
| or FPGAs for that, sure, but the point is that the FP
| unit on the CPU is usually way to slow for anything more
| serious.)
|
| > Hardware support is also extremely important for games
|
| That's more or less the only valid usage in mainstream
| left by now. But even there:
|
| > but floats are not a good representation for most of
| it.
|
| Exactly!
|
| As said, you could and should use ints for most things.
| For the rest you want actually _rationals_. Only in some
| very special circumstances floats are a good enough
| approximation. But the cases where this is true are
| mostly related to rendering, as it doesn 't matter if
| some pixels shown for the fraction of a second have a
| marginally wrong color or are marginally off. But
| rendering is done on the GPU anyway. So again no reason
| to use FP features on the CPU.
|
| Even games using vector and quaternion math extensively
| this is just lib code in the engine. So there is no real
| reason this couldn't be moved to the GPU also, given an
| adequate architecture of the game engine. Such an
| approach brings even amazing possibilities for games;
| just have a look at for example https://store.steampowere
| d.com/app/1468720/Ultimate_Epic_Bat... Want to animate 10
| million of individual NPCs? No problem, if you do it on
| the GPU!
|
| So imho the case for FP on the CPU is very shallow. But
| the need for rationals and decimals is a real thing.
| That's what the average cooperate developer needs day to
| day.
|
| It's a shame HW is stuck in the past since decades and
| there is still no promise of progress on the horizon.
| (Maybe FPGA accelerators build into CPUs will change that
| at some point. But we still don't have that, even it's
| overdue.)
| gizmo wrote:
| You mean fixed point numbers presumably, because at the
| time using integers that use a variable amount of memory
| was totally out of the question. Today it's still terrible
| for performance because you can't use caches and simd
| effectively when numbers can't be packed directly in
| arrays.
| zelphirkalt wrote:
| Does AoE2 do that? Packing numbers directly into arrays?
| Or does it rather deal with objects, which are variable
| size anyway? I am not sure how much high performance work
| has been done in AoE2. Maybe not that much.
| camgunz wrote:
| I dug into this problem a while ago and came to the
| conclusion that these are all rounding problems, which you
| still can't escape with arbitrary precision systems,
| because memory is finite. You're always making a tradeoff
| between precision and space, and you have to rely on
| programmers to make that tradeoff themselves.
|
| Enter the typical floating point types that do some of that
| work already: float/double. These let you not think (as
| much) about the memory your math might take up, but they
| still need you to think about rounding, which almost no one
| does.
|
| This is a long winded way of saying that if you set up your
| arbitrary precision arithmetic library to use 4 bytes and
| the same rounding mode (the default is round to nearest) as
| was used here, you'd reproduce the bug. You'd also
| reproduce the 64-bit bug moving up sizes, and the
| 128/256/etc bug. You gotta round.
|
| The good news, though, is that actually solves it! You can
| even use floats for money!
| pclmulqdq wrote:
| If you have integers that are stored in floating point types
| and don't need more than [mantissa] bits of precision, you
| can operate on them like ints and always* get the right
| result. Nobody would expect that the formula `return
| new_maxhp * (old_hp / old_maxhp);` would work with ints, but
| they see floats as magic that allow them to drop their guard
| about precision and rounding of operations. Unfortunately
| not.
|
| Rationals have a big problem where under multiplication and
| division they need to be re-normalized periodically, and that
| re-normalization is slow (running gcd). Under addition and
| subtraction, rationals are great.
|
| *the one big difference is that division rounding is
| different
| filmor wrote:
| None of these would be a problem if people would round
| instead of truncate by default.
| BeetleB wrote:
| > The old "Multiplying and dividing is associative... for the
| set of reals
|
| Psstt... Dividing is not associative for the reals.
| kaslai wrote:
| I think the original intent was referring to the fact that
| given the same operand, the order of multiplication and
| division shouldn't matter, e.g. A * X / X should give the
| same result as A / X * X, but in reality they can give
| different results when done by a computer due to precision
| limits, overflow, etc.
| BeetleB wrote:
| Ah that makes sense.
| thrdbndndn wrote:
| Could you explain to a noob why does this happen, exactly?
|
| Is it because 55/55 != 1, or 1*1 != 1?
|
| I understand float can't store certain integer/finite decimal
| precisely, but why would a/a not be 1 if both numerator and
| denominator are the same (imprecise) number?
| zem wrote:
| it's because the calculation (1/ 55) is less than the real
| number 1/55, so when you multiply it by 55 you get a result
| less than 1.
|
| for an easier to follow example, say you can only work with
| two decimal places, hp was 1, old max hp was 3 and new max
| hp was also 3. if you do (3 * 1) / 3 you get 3 / 3 = 1 as
| intended. if instead you do 3 * (1 / 3) you get 3 * 0.33 =
| 0.99 which is less than 1
| zelphirkalt wrote:
| This effect becomes more pronounced, when substracting
| (but probably also adding) small amounts from big
| amounts, because more bits are needed to store the big
| number's more significant digits and floats then lose
| bits for the less significant digits. That is why, if one
| needs precision, needs to sort numbers first and then
| start calculating with the smallest numbers first,
| working ones way up to the bigger numbers.
| thrdbndndn wrote:
| Thanks!
|
| I misread the equation and thought it's `old_hp *
| (new_maxhp / old_maxhp)`.
| foota wrote:
| It's neither. Diving 1 by 55 gives some number x where x is
| arbitrarily (there are standards for how to choose) chosen
| between the closest 2 representable floats to 1/55. Then,
| they multiply x by 55. If x is bigger than 1/55 here then
| the result is > 1. But, if it was rounded down then it will
| fail because x * 55 will be less than 1.
| layer8 wrote:
| > So it should have been `(new_maxhp * old_hp) / old_maxhp`.
|
| I don't see how that couldn't run into similar problems. I
| would use `clamp(old_hp * (new_maxhp / old_maxhp), 1,
| new_maxhp)` (assuming that old_hp >= 1).
| iforgotpassword wrote:
| It could, but only at very large values. It's at least the
| much more robust solution.
| tpolzer wrote:
| If you assume that all three numbers are small integers,
| doing the division last minimizes precision loss (and
| doesn't have any loss if the accurate result is
| representable as a float).
|
| Otherwise you get loss from the division and then multiply
| that loss (by >1).
| m463 wrote:
| I wonder if the fix would be vulnerable to "nudging" hit points
| up by picking up and dropping a relic? :)
| ummonk wrote:
| Suppose someone with 1 hitpoint actually transformed into a unit
| with less hitpoints - should they then die? Seems to me the fix
| should be to represent hitpoints as integer values, and round up
| during conversion.
| vishnugupta wrote:
| What's the best way to play AoE on a MacBook? I can't afford a
| dedicated game rig so any pointers would be of great help.
| rwalle wrote:
| Probably not the answer you were expecting, but you may want to
| consider getting an Xbox Series S (that is often on sale at
| $250 or even $200), plugin your mouse and keyboard and you'll
| have a great experience. Yes that is a "dedicated game rig" but
| much more affordable than a usable gaming PC. Of course, only
| if you also play other games on that xbox and can live with no
| disc. This is what I would do in your situation.
| Sakos wrote:
| This is what I found for the M1
| https://old.reddit.com/r/macgaming/comments/ms8081/age_of_em...
|
| Seems to work fine with Wine and Crossover.
| steivan wrote:
| I use a small machine at Paperspace (P4000 with 100GB) and play
| it remotely with Parsec. The experience is very good and costs
| me about 10-15$ a month.
| moffkalast wrote:
| How is it that a modern laptop manages to be worse at gaming
| than the average PC 20 years ago? Surely you one can at least
| run it in an emulator of some kind?
| qwytw wrote:
| You can just run with Wine, it seems to work mostly fine.
|
| Also you could probably just install ARM Windows in a VM,
| not sure how good is the Windows translation thing compared
| to Rosetta though you might end up with a worse experience
| than just by using Wine.
| qprofyeh wrote:
| Guess that's what those Epsilon checks are for.
| riffraff wrote:
| This is a fantastic out of context change log.
|
| For even more abstract ones I cannot recommend enough the Dwarf
| Fortress Bugs Twitter account[0]
|
| The last of which is
|
| > Flying creatures keep exploding into pieces and dying: Are they
| crashing into trees?
|
| [0]sadly no Mastodon, https://twitter.com/DwarfFortBugs
| a_e_k wrote:
| Paradox Interactive games, especially the Crusader Kings series
| also have some pretty entertaining change logs. E.g., from
| Crusader Kings II, Patch 2.4 [0]:
|
| - Handsome and lustful men now also populate the cabins in the
| wild for the pleasures of people who find them attractive.
|
| - Characters who love their spouses very much are now less
| likely to join holy orders.
|
| - Paranoid parents should no longer worry about potential plots
| against dead children.
|
| - Fixed that bedtime stories can no longer be told to dead
| children
|
| - You no longer punish yourself when a prisoner tries to flee
| from your prison by charming the guard.
|
| - The Orthodox Patriarch is now concerned if Orthodox rulers
| have heathens in their court.
|
| - Discovering two vassals of the same sex engaging in carnal
| activities during pagan feasts no longer let's the liege join
| in on the fun.
|
| - Ambitious claimant adventurers now move out of the realm if
| they are targetting their liege
|
| - No longer possible to banish your spouse or concubine
|
| - Decreased monthly decadence gain.
|
| [0]:
| https://forum.paradoxplaza.com/forum/threads/patch-2-4-chang...
| m463 wrote:
| Wow, the logic to model these kinds of social structures
| makes my head hurt. But you would have to do it.
|
| And I wonder about dead children. I remember one game where
| there could be no dead children.
| SXX wrote:
| And in CK you can actually sacrifice a child for some
| gains.
| djur wrote:
| Starting sometime in the mid-'00s it became common practice
| to prevent players from gratuitously killing child NPCs. As
| I understand it, this was to comply with ratings boards. A
| good example of the change is Fallout. Fallout 2 had child
| NPCs with no invincibility, and in the German release they
| just made the children invisible and untargetable. This
| caused some issues. In Fallout 3 children can't be damaged
| by the player, but you can cause their offscreen deaths
| (with a nuclear bomb, even). Similarly, I think Crusader
| Kings can get away with it because there's no visual
| depiction.
|
| As an aside, while I understand the motivation for this
| kind of thing, I remember finding a child's body after a
| firefight in Deus Ex and having a moment of moral anxiety
| as I wondered whether it had been one of my stray bullets
| or someone else's (or even unrelated to the fight).
| mcv wrote:
| If you don't want to see terrible things happening to
| children, I'm afraid CK is not the game for you. The game
| goes out of its way to model the worst aspects of medieval
| life.
| [deleted]
| boomboomsubban wrote:
| The logic is less complex than you'd think. It's generally
| something like "has flag paranoid, has flag child (patched
| to has flag alive child), then 1% yearly chance of fearing
| a plot." It feels complex, thinking of the actual logic
| killed a fair amount of the fun for me.
|
| >And I wonder about dead children. I remember one game
| where there could be no dead children.
|
| Probably Skyrim, though it's not rare. Crusader Kings
| somewhat encourages infanticide, as your brother's bastard
| could stop your character from inheriting a title.
| tetha wrote:
| > The logic is less complex than you'd think. It's
| generally something like "has flag paranoid, has flag
| child (patched to has flag alive child), then 1% yearly
| chance of fearing a plot." It feels complex, thinking of
| the actual logic killed a fair amount of the fun for me.
|
| But doesn't this overlook the emergent complexity from
| many actors running these simple rules, plus interactions
| between them?
|
| A lot of the shenanigans in Dwarf Fortress arise from
| relatively simple actors following their relatively
| simple plan, until those plans clash or interact with
| each other and crazy things start happening - such as
| prioritizing drinking booze over pulling a lever to lock
| out a monster.
| boomboomsubban wrote:
| >But doesn't this overlook the emergent complexity from
| many actors running these simple rules, plus interactions
| between them?
|
| Somewhat, but it more feels like "wait for good flag, try
| to activate good flag events. Wait for enemy to have bad
| flag, try to activate bad flag events." Other's find it
| has lasting fun despite that, but I found I lost
| interest.
| riffraff wrote:
| These are great, they make me want to play the game!
|
| Although I'm not sure why a threesome during a pagan festival
| has become illegal, I'd have considered that a feature, not a
| bug.
| acheron wrote:
| There was a bug fix in Nethack a few years ago to make eating
| parchment spellbooks break vegetarian conduct. Which at one
| level makes perfect sense: of course parchment is an animal
| product. But the fact that it comes from the intersection of
| several kind of weird systems in the game made it such a great
| Nethack bug. First, that the game tracks vegetarianism at all.
| Then, the randomized unidentified item descriptions that are
| mostly flavor text but occasionally have gameplay properties.
| And finally, why are you eating spellbooks in the first place?
| schoen wrote:
| As opposed to eating rings, which can permanently give you
| the associated magical intrinsics (without having to wear the
| ring). This, in turn, means that which specific intrinsics
| you can get that way various from game to game (because you
| can temporarily polymorph into a metal-eating monster, but
| some rings are metal and others aren't).
|
| https://nethackwiki.com/wiki/Eating_jewelry
| agumonkey wrote:
| When read with a history bias, that title makes for a long and
| deep source of confusion.
| dragontamer wrote:
| I mean, Age of Empires 2 is a very historical game. Everyone
| knows that the Halberdiers of the Inca are pretty good
| especially when paired up with Inca's famous archers: their
| Crossbows and Arbalesters. /s
|
| These historical games have two ways of doing things. Staying
| historically correct (which is unbalanced... such as Hearts of
| Iron where Soviets + Germany will likely crush Poland in the
| first move every game), or you balance the game so that
| everyone has a fair chance like AoE2. But balancing the game
| naturally introduces significant ahistorical aspects.
|
| --------
|
| AOE2's historical campaigns are pretty good though, and
| somewhat representative of famous battles throughout history.
| sprain wrote:
| Not knowing it was about a game, that was one of the strangest
| headlines ever to read on here.
| 0xpgm wrote:
| Likewise, I thought it was something to do with blood pressure
| :)
| neom wrote:
| Conversely, I didn't even have to even click in to understand
| it hah. Been playing AoE for around 20 years.
| alternatetwo wrote:
| I was confused as well, because I just had chatted with
| someone about whether the aoe2 monk conversion ability on
| certain buildings was hardcoded or not (they can't convert
| i.e. Town Centers, Monasteries) ... turns out it at least
| used to be, no idea about now.
| 1024core wrote:
| I had no clue what the headline was all about. I imagined some
| Aztec monks with a 1/55 HP motor trying to do something and just
| dying for no reason.
| shilgapira wrote:
| What a weird coincidence. I thought at first this would be about
| the Guild Wars game, but turns out they both have something to do
| with monks and 55:
|
| https://wiki.guildwars.com/wiki/55_Monk
| hobofan wrote:
| Yeah, really the only word out of place in the headline was
| "Aztec". All the rest could have applied to GW.
|
| Fun fact: In the early days (I think the first 6 months or so)
| of GW there were some item attribute modifiers that I think
| allowed for going as low as 5 hp, making the character
| basically invincible, as all damage was rounded down.
| dvngnt_ wrote:
| farming ectoplasm lfg
| voz_ wrote:
| Ahh nostalgia. I thought so too. This was such a fun build. I
| miss GW1 a lot, GW2 missed the mark, and is no true successor.
| Sakos wrote:
| Man, I miss GW1. That skill/class system was amazing and
| still goes unmatched in its flexibility and depth today.
| dimgl wrote:
| I want to create a spiritual successor to this but I'm only
| a dev, and not an artist. It's really killing me. I want to
| make a game like this before I die, but it's looking
| unlikely.
| zeeZ wrote:
| Depends on what you're after. In terms of mechanics it's a
| completely different game, but lore wise a phenomenal amount
| is tied in to GW1. It's almost fan service: the game.
| dimgl wrote:
| Wow, another 55 monk enjoyer. I used to farm hydras outside of
| the Crystal Desert with this.
| system2 wrote:
| I was stopping myself from buying Definitive Edition but I guess
| I am buying it today...
| dragontamer wrote:
| Note that the April 2023 patch is live, and perhaps one of the
| biggest changes to the meta ever. I don't think anyone really
| knows how the new meta will shake out.
|
| Build orders will absolutely change this patch. Though I guess
| that only matters if you were hoping to get to a competitive
| level.
|
| Definitive Edition does have a very good tutorial mode for
| people interested in online combat, and "Extreme" AI is 100%
| legitimate (AoE2 Extreme does NOT cheat, you're fighting it
| fair-and-square, but Extreme does a proper build order so it
| just "feels" quick if you haven't studied build orders yet)
| fauxpause_ wrote:
| What's new? Seems kind of crazy to introduce a meta changing
| past to an old game like this that has managed to stay
| popular.
| dragontamer wrote:
| Pre-patch, the meta was growing a bit stale and settling
| upon Crossbows play, or Knights play. (Or sometimes:
| Crossbows + Knights). An odd greedy defender might go
| Mangonel (aka: Anti XBow) + Monks (aka: anti-knights), but
| the game pretty much revolved around Archers (for civs like
| Britons) or Knights (for civs like Franks), and their
| closely related counter-units.
|
| EDIT: case in point. Vikings, a civilization with numerous
| infantry buffs, was played as an Archer civ in practice
| because even with all their infantry buffs, XBow / Arbalest
| was considered stronger.
|
| The biggest change this patch is a new tech for +1 pierce
| armor to the Longswords line, which can be researched in
| Castle Age. Furthermore, the entire line of infantry can
| upgrade faster, and cheaper. Finally, most infantry civs
| (Malians, Goths, etc. etc.) have gotten significant economy
| buffs to make them even stronger. Whether or not its enough
| for infantry to shine is to be seen.
| qwytw wrote:
| > old game
|
| They have been releasing expansion adding new civilizations
| every ~6 months or so together with a bunch of balance
| changes.
|
| > stay popular
|
| It didn't. Not too such an extent as it is now. For years
| it had only community support and a fairly small player
| base. Microsoft resurrected it not so long ago.
| pomber wrote:
| To be fair, it may be the "biggest change ever", but it
| doesn't change too much. It buff some units that were bad,
| nerf some units and techs that were too good. But the
| general meta remains the same. The devs are really good at
| introducing changes.
| dayjaby wrote:
| Several infantry civs like inka, sicilians, slavs, vikings,
| celts and dravidians got _many_ huge buffs. Main change to
| like 50% of the civs is called gambesons, which adds 1
| pierce armor to the militia line, basically reducing the
| damage they get from skirmisher by 50%.
| CorrectHorseBat wrote:
| More buffs to infantry. Players got better and infantry was
| barely used.
| arbitrandomuser wrote:
| There has been drastic meta changes before too but over the
| years the units that have been made has remained the same.
| The earlier meta mostly used to be around archers or
| cavalry , infantry was simply not viable except with
| certain civilization(goths) and that too only once you had
| the whole economy set up to spam their cheap infantry
| continuosly.
|
| Theve been trying to push infantry with small buffs , and
| this is patch has seen some more buffs to infantry and
| infantry civs.
| the__alchemist wrote:
| In addition to the infantry gradual bufs, full-walling in
| Feudal using a mix of palisades and houses became
| ubiquitous. Pallisades, buildings-as-walls etc were
| gradually nerfed. Still popular, but now there's a higher
| associated cost. I wonder if they're done with those nerfs,
| or if there's another coming. (Since this technique is
| still very strong... Or maybe it's that scout rushes are
| strong!)
| fauxpause_ wrote:
| How was walling with housing nerfed? I remember doing
| that a lot.
| the__alchemist wrote:
| In-progress buildings are easier to destroy IIRC.
| Palisades cost more and are slower to build.
| vippy wrote:
| What's up with all of these 18 feudal builds?? And to Hell
| with the Portuguese fast castle, organ gun OP on arena.
| dragontamer wrote:
| It was always possible to do 18 pop feudal, but today's
| focus on luring deer is perhaps the biggest change to the
| meta?
|
| There wasn't any real balance patch. Just people who have
| gotten much better at luring deer to improve early build
| orders. Like 3 years ago, you'd just assume 2x Boar + 8x
| sheep as your early food source. But today, people are
| adding 2x or even 3x deer to that.
|
| As deer + boars collect food at the fastest rate, you can
| more consistently go up at lower villager counts. There's
| also much more precision: killing boars / deer / sheep
| under the town center more consistently today than before.
|
| --------
|
| TL;DR: Skill improved, people can do 18 pop today even
| though its always been possible. So people are just getting
| faster and more optimized.
| dayjaby wrote:
| Hera made a video about this recently and attributes it
| more to all the QoL updates like shift queueing. Sheep
| actually spawn next to your TC now. Before DE you had to
| find your first 4 as well.
| devjab wrote:
| The thing I like the most about this is how the game actually
| switches out a unit with a different unit depending on the task
| the unit needs to do. It's not exactly in the reddit post, but
| rather in the video https://www.youtube.com/watch?v=MytWNbpnAVY
| where the error is outlined. What a brilliant way to keep
| complexity down.
| olalonde wrote:
| Fun fact: The competitive AoE2 scene remains very much alive and
| thriving. Several top players are able to make a living from it,
| thanks to streaming revenue and tournament prize money. There are
| even some streamers, such as T90 and MembTV, that have managed to
| create successful careers despite not being competitive players
| themselves.
| dragontamer wrote:
| Note that T90 is like 2300 Elo. Which isn't "top level pro",
| but I'm pretty sure he'd kick most of our asses.
|
| T90 is probably the strongest dedicated commentator / announcer
| / caster in this community.
| justrealist wrote:
| tbh I credit ZeroEmpires with keeping the community alive
| through the slower times though.
| arendtio wrote:
| And some players have come a long way. One of my highlights
| was, when DauT won the Red Bull Wololo 3 tournament as someone
| who is playing the game 20+ years. And some fans are doing
| great stuff too, like this video that was released shortly
| after (DauT is back):
|
| https://www.youtube.com/watch?v=_u-SisO8ers
| syspec wrote:
| This game is still amazing. I never played it as a kid, but
| bought the Definitive Edition last year on steam. Already have >
| 600 hours on it.
|
| Beat RTS ever in my opinion.
|
| Check out big tournament to get an idea of the current scene:
| https://youtu.be/6krbA4jTUqE
|
| Also I didn't play multiplayer until last month, most of that 600
| hours was spent in the many many excellent single player
| campaigns
| winrid wrote:
| Immediately noticed how the font on the MS's site is very
| readable. "noto-sans", evidently
___________________________________________________________________
(page generated 2023-04-15 23:01 UTC)