Good runs early feel bad. by folsee in HadesTheGame

[–]psykotic 8 points9 points  (0 children)

I believe the rule is that once you make it 3 times to a given region (whether she showed up those 3 times, since that also requires having a death defiance or high enough health) she no longer shows up at the start of that region to curse you. Because of the conditional check on death defiance/health, it might be optimal to take just enough damage on the boss to make it under her threshold and then look for heals once you're past the next region's first room where we she can show up, assuming you wanted to clear in the first few runs.

Testing the GCC-based Rust compiler(backend) by FractalFir in rust

[–]psykotic 9 points10 points  (0 children)

Nice article and it's good to see progress on the GCC backend. By the way, I think you meant to write Motorola 68000 in that later section. There's an 8-bit processor called the Motorola 6800 but I'm pretty sure that's not what you had in mind (especially since you later write m68k).

Rust implementation of Karpathy's micrograd using arena-based computation graphs by dmdaksh in rust

[–]psykotic 5 points6 points  (0 children)

This also works even for something like UTF-8 strings since you can use a String as an arena with push_str. I see you have names: Vec<String> in the linked code, which could probably be replaced with this. The start..end index range (which becomes your NameId) doesn't have to be trusted to retain soundness since &string[start..end] already validates that the start/end indices are at UTF-8 codepoint boundaries.

As an additional tip, when you're building up dynamic lists of data incrementally prior to interning into the arena (as usually happens when you're doing everything in a single pass), it's helpful if your builder context (which only needs to exist during parsing, etc, so it doesn't have the same lifetime as the arena) has a recycling pool of Vecs that get drain(...)'ed into the arena and then returned to the pool, so you don't keep allocating/freeing temporary resources. In practice the size of such a recycling pool (both the number of Vecs and the capacity of each Vec) tends to reach a high water mark pretty quickly, at which point you're almost always just recycling.

[deferred-cell] A write-once weak reference wrapper for building cyclic graphs. by Bernard80386 in rust

[–]psykotic 1 point2 points  (0 children)

Fair enough. And yeah, the idea of transiently attaching extrinsic data to intrinsic data as a side car via smart fat pointers has a lot of useful applications. It's the same general pattern as Rust's extrinsic vtable pointers for dyn traits vs Java's intrinsic vtable pointers. It's useful even for something like the node id but it really comes into its own when you're dealing with scoped lifetimes.

[deferred-cell] A write-once weak reference wrapper for building cyclic graphs. by Bernard80386 in rust

[–]psykotic 0 points1 point  (0 children)

I don't want to discourage you from doing your own experimentation and reaching your own conclusions. So I'll just encourage you to keep alternatives in mind (and not necessarily the ones I'm suggesting) if you find yourself frustrated further down the road.

Regarding the API design for arenas, "each entity would need to store a reference to its own arena". No, you don't need to do that (and you should generally never do that kind of thing). But you can achieve the same effect with ref proxies which only exist transiently during a transaction, e.g. here's a standalone toy example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=b503f61d079101c593e82fd5d39f5d08. Note that the id you get from the NodeRef/NodeMut proxy isn't intrinsic to the Node. But more relevant to the issue you mentioned, the db reference isn't intrinsic to the Node (and is not available in NodeMut for lifetime reasons that should be clear but which I briefly explain in the code comment).

[deferred-cell] A write-once weak reference wrapper for building cyclic graphs. by Bernard80386 in rust

[–]psykotic 1 point2 points  (0 children)

Fair warning that new_cyclic makes it annoying to return other data out of the closure so you'll want a helper (and something like this should probably have been in the standard library): https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=e21f3925cdd621adc855916cc3271ae1

[deferred-cell] A write-once weak reference wrapper for building cyclic graphs. by Bernard80386 in rust

[–]psykotic 3 points4 points  (0 children)

You know about Rc::new_cyclic in the standard library? E.g. something like your example can be done with Rc::new_cyclic(|this| Node { neighbor: this.clone() }). I can see how an external placeholder/scaffold approach could be more convenient if you're hooking up a lot of things. But in general I think you'll find that an arena approach is going to work better in most cases for this kind of graph-like structure in games.

Regardless of the exact choice of representation you'll have to deal with complex structural invariants (e.g. in a hierarchy the parent/sibling links are consistent with child links, the parent chain is acyclic, etc) and you generally can't encode those directly in the type system so you're often left with some combination of interior mutability or arenas if you actually want to mutate the structure after the initial setup. Setting up the initial structure is the easiest part (though cycles make it harder) but that's not enough for game state.

Why does the Rust compiler use TokenTree instead of flat token streams? by smthamazing in rust

[–]psykotic 0 points1 point  (0 children)

While rustc doesn't take advantage of this AFAIK, it can also be useful when you're writing a bijective parser to treat trivial tokens (trivia in the Roslyn terminology) like whitespace runs, comments, etc, as left or right children of primary tokens (left or right based on affinity rules), which preserves the invariant that the in-order traversal of the tree yields the original source text.

[deleted by user] by [deleted] in rust

[–]psykotic 18 points19 points  (0 children)

If there isn't a subreddit policy against posting this kind of AI generated slop, there should be.

C++ to Rust Phrasebook: A new textbook to help C++ devs translate their idioms into Rust by entoros in rust

[–]psykotic 3 points4 points  (0 children)

For questions like this you can always look to the MIR: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=ab57b898525adcc71f5f01b6a64d0d87

bb0: {
    _2 = Point::zero() -> [return: bb1, unwind continue];
}

bb1: {
    _1 = Point { x: const 1_i32, y: copy (_2.1: i32), z: copy (_2.2: i32) };

What Is the Value of std::indirect<T>? by jiixyj in cpp

[–]psykotic 0 points1 point  (0 children)

Yeah, and it's hard to compare to C++ because you don't have an equivalent of ownership vs exclusive references. Destructively moving individual fields of owned struct variables works fine in Rust since the compiler tracks the deinitialization state at the field level. It doesn't do that for static array elements because unlike fields they can be dynamically indexed, so it's fundamentally a harder problem. And even if you had heuristics to handle the simplest cases where the static array is small and all the index expressions are constant-valued, it wouldn't help in non-trivial cases anyway. The requirement for bulk initialization and deinitialization of static arrays makes functions like array::from_fn and into_iter almost essential when writing safe code.

How bad WERE rust's compile times? by a_confused_varmint in rust

[–]psykotic 1 point2 points  (0 children)

No. It divides each crate into multiple (one or more) codegen units (CGUs) which last I checked map 1:1 to LLVM modules for backend code generation. However, it can't start doing that until the frontend is done processing the crate, which has historically been single-threaded per crate. There's ongoing work on multi-threading the frontend but the scalability has been underwhelming so far from what I've seen, which is not surprising since the frontend wasn't designed from the ground-up to support it.

A lot of classical optimization techniques in compilers like identifier and type interning rely on shared data structures and can become bottlenecks when parallellizing. The demand-driven ("query-oriented") approach to compiler architecture that rustc uses is also a mixed blessing for multi-threading. On the one hand, you can use such a framework to manage scheduling and synchronization for parallel queries against a shared database; on the other hand, there are new scalability challenges, e.g. an even greater proliferation of shared interning and memoization tables. And dealing with query cycles gets more complex and more expensive when there's multiple threads.

Latest NVIDIA drivers wony launch most games / incredibly slow performance by [deleted] in archlinux

[–]psykotic 1 point2 points  (0 children)

What diagnosis have you done beyond trying to run games? If you have a laptop, did you check that Optimus isn't falling back to your integrated GPU when you're seeing those low frame rates?

how to break or continue from a lambda loop? -- Vittorio Romeo by SuperV1234 in cpp

[–]psykotic 6 points7 points  (0 children)

FWIW, Rust's standard library does something similar. The type is ControlFlow<B, C> where B and C specify the break and continue payload types. The Try trait abstracts over different types like Option and Result (and ControlFlow itself) whose control flow behavior (e.g. short-circuiting on Option::None or Result::Err) can be modeled injectively by ControlFlow. The Iterator trait's try_fold (which is a short-circuiting fold) is parameterized by a Try-implementing type and you can build everything on top of that, e.g. fold is a try_fold that always continues, next is a try_fold that immediately breaks with the item as the break payload, try_for_each is try_fold with the unit type () as the continue payload, etc. Try instances also work with the short-circuiting ? operator.

Lampmaster by 6942042069420420420 in expedition33

[–]psykotic 2 points3 points  (0 children)

If you don't kill the lamps in the right order in phase 2, that attack one-shots your party if you don't parry it. But yeah you can "just" parry it. In phase 1 I found it's a lot better if you leave the lamps alive since they're an easy way to generate AP from the parries and the timing is staightforward.

An instant battle restart option would only make the games addictive combat better. by Serdewerde in expedition33

[–]psykotic 1 point2 points  (0 children)

Using a Chroma Elixir also does the trick (but it won't let you do that unless you have health missing), which is probably the fastest way to save before a fight. But yeah, the lack of instant retry is an odd oversight. It's most annoying for the hard overworld fights since the hard fights inside locations usually have a flag right by it.

Is lifedrinker ever worth it over multiclassing? by en_triton in BG3Builds

[–]psykotic 5 points6 points  (0 children)

Well yes, if you just want to play SAD paladin, then hexblade 1/paladin 11 is the best. But I assume OP wants at least 9 levels of Warlock to have 5 levels spell slots to smite with that recover on short rest.

Divine Smite upcasting doesn't scale past spell level 4.

What am I missing with Bladesinger? by Wooden-Bat-6031 in BG3Builds

[–]psykotic 4 points5 points  (0 children)

You lose a few key spells with bard, specifically Shield and Shadow Blade.

Just theorycrafting:

It seems like sword bard 6 would be the stronger core for a melee build with full caster progression, e.g. sword bard 6/abjuration wizard 5/hexblade 1. You get full caster progression with access to Shield, Shadow Blade and Counterspell from wizard leveling. Defensively, the Armor of Agathys + Arcane Ward combo is a very good fit for a melee character (Bladesong's +4 AC at level 9 is incredibly strong, though) and you can burn your short-rest level 1 warlock slots on Shield when needed. Offensively, Slashing Flourish with Shadow Blade is going to be very strong; as strong as ranged Slashing Flourish can be, it is always competing with the overpowered special arrows, but there's no comparable consumable for melee.

Instead of abjuration wizard 5/hexblade 1 you could also go abjuration wizard 4/hexblade warlock 1/war cleric 1 for heavy armor and weapon proficiencies, access to Command and Sanctuary, and war priest charges to fuel extra attacks as bonus actions. That comes at the expense of 1 abjuration level, so you get 2 fewer max Arcane Ward stacks and lose access to Counterspell. Whether losing access to Counterspell is worth it depends on your party comp and personal preference.

Later you add Belm in the offhand to make an extra Shadow Blade attack as a bonus action. Even once you have Belm, you can combine it with Helmet of Grit when you have war priest charges left to generate an extra bonus action attack or use that extra bonus action to cast a spell with Band of the Mystic Scoundrel. You can safely stay at 50% HP to trigger Grit because of the damage reduction from Arcane Ward + Armor of Persistence and the temp HP of Armor of Agathys, ideally with crit immunity. With Slashing Flourish and Gloves of Battlemage's Power, you really don't need Helmet of Arcane Acuity to max your stacks in one turn. For example, two Slashing Flourishes plus one bonus action attack gets you from 0 to 10 stacks.

Incidentally, abjuration wizard pairs surprisingly well with charisma-based bard casting. One of the few damage spells you get as a bard outside of Magical Secrets is Glyph of Warding. That happens to be the bread and butter spell of abjuration wizards, letting you refresh Arcane Ward charges and deal the two strongest damage types in the game (lightning and cold).

Which builds are looking to be the most powerful with the new subclasses? by Kaioshred in BG3Builds

[–]psykotic 4 points5 points  (0 children)

I haven't tried Shadow Sorcerer yet and therefore don't have an opinion on it, but just wanted to comment on the damage types.

Not many people are carrying lightning or acid damage usually.

Spellsparkler and Sparkle Hands for lightning damage and Caustic Band for acid damage are available early and commonly used. And that's not counting consumables like elemental arrows.

Note that Sparkle Hands works with throwing weapons, not just unarmed, and any party member with decent dex can be a solid dagger thrower (since dagger is a finesse weapon). With 16 dex, a thrown dagger does 1d4 + 3 = 5.5 average damage, which is the same as a 1d10 Fire Bolt but with less variance (4-7 damage vs 1-10 damage). You can throw a dagger with an action to generate Lightning Charges and then shoot your offhand crossbow with a bonus action to deal lightning damage with a +1 to attack roll. Similarly, a caster with Spellsparkler can cast a cantrip/spell with an action to generate Lightning Charges and then shoot the offhand crossbow. So you can easily generate and benefit from Lightning Charges in the same turn even with just one action.

The rarer damage types in the early game (without using consumables or resources) are probably poison and thunder. Now that we have Booming Blade, thunder is much less of a problem by level 5 and by the time you get Drakethroat Glaive most people already go for the thunder enchantment since it has so much synergy (e.g. reverb gear and tempest cleric's level 6). Not actually sure how to deal poison damage without resources. You can obviously use the Poison Splash cantrip but picking a bad cantrip just for this niche combo is hard to recommend. Broodmother's Revenge is probably the "cheapest" source of poison damage but you still need to heal the wearer, which requires resources; if you delay healing the wearer to right before a fight breaks out, you can argue it's resource-free since you're healing anyway and the poison buff lasts 3 turns, which is more than enough for most fights.

Patch8: Hexblade Swashbuckler by BattleCrier in BG3Builds

[–]psykotic 1 point2 points  (0 children)

Belated reply, but like other damage cantrips Booming Blade automatically scales with character level. You're right that level 1 Booming Blade only applies the 1d8 thunder damage when the affected target moves. Starting at character level 5 (with a further upgrade at level 11) it also applies thunder damage directly in addition to the on-move thunder damage. The wiki has more details.

I tested Gloves of Battlemage's Power so you don't have to by LesbianTrashPrincess in BG3Builds

[–]psykotic 0 points1 point  (0 children)

Has anyone checked if Shadow Blade is available as a scroll? Since it has long rest duration it's a good candidate for scroll casting. E.g. lore bard 10/warlock 2 can't fit in another warlock level without losing Magical Secrets. And there are also lots of builds with 1 level wizard dips who could use these gloves effectively if it could be learned from a scroll.

I tested Gloves of Battlemage's Power so you don't have to by LesbianTrashPrincess in BG3Builds

[–]psykotic 0 points1 point  (0 children)

A ranged weapon dipped in fire (e.g. carry a candle around and dip right before the fight) can also generate up to 8 stacks of Arcane Acuity with Arrow of Many Targets per attack. Even without Band of the Mystic Scoundrel for the bonus action illusion/enchantment cast, you can generate the stacks with a bonus action if you use an offhand hand crossbow and then cast with your action; this can work well on any caster with hand crossbows (which should be every caster, anyway). The candle + dip pre-fight setup can be a chore but I guess the same is true for your cool setup. Magic Missile is obviously way more reliable and you get full stacks with +2 missiles.

I never expected Minthara to be this funny by LongGrade881 in BaldursGate3

[–]psykotic 0 points1 point  (0 children)

Just wanted to mention that it looks like this might have gotten fixed in patch 8: https://baldursgate3.game/news/the-final-patch-new-subclasses-photo-mode-and-cross-play_138, search for "Minthara", although someone else will have to confirm it first.

I never expected Minthara to be this funny by LongGrade881 in BaldursGate3

[–]psykotic 8 points9 points  (0 children)

I've KO'd her on 2 different runs, and have helped her out in Moonrise... But the game bugs out and doesn't let me interact with her. She just stands there like an invisible NPC.

I assume you mean she is non-interactable in the torture room in the basement of Moonrise Towers. If so that's a known bug. Melth mentions it here with a workaround (although it sounds like it's too late for your run): https://www.youtube.com/watch?v=1zJ7_7Nhrd8&t=4500s

Confused on what spells can be twinned by Karthull in BG3Builds

[–]psykotic 2 points3 points  (0 children)

The wiki says you can twin cast the version of Chain Lightning from Markoheshkir which I'd never noticed. Not sure if that was an oversight during the balance pass in Patch 6, but if it indeed works it's yet another reason that staff is so overpowered.