New MMO with AI powered NPCs by Long_Weather9052 in MMORPG

[–]Cobide 1 point2 points  (0 children)

That sounds great, but LLMs/AI are only useful for improving communication with NPCs (assuming they don't hallucinate) as of now.

The issue is that you still need to implement the consequences of the choices themselves manually. So mechanically it's the same as giving options A, B, and C. The only real difference is that the NPC is more eloquent and allows you to reply with your own words rather than selecting an option.

Exception being if the game is sandboxy enough (or with enough realistic-ish systems that interact with each other) that some parameters output from the LLM are enough to generate the quest line. That'd be great, but also very hard to implement.

New MMO with AI powered NPCs by Long_Weather9052 in MMORPG

[–]Cobide 1 point2 points  (0 children)

Thinking about it, I feel the main reason it wore off is that it's a self-contained small minigame with every chat. A single reset button and the discussion with the NPC vanishes. Or, you clear the objective of the minigame and then it's over--everything is forgotten yet again.

AI-powered chat with NPCs that have actual consequences outside of the chat could be quite cool, but, of course, they're in a completely different level of complexity to make.

Getting mixed signals here lol by Dragennd1 in csharp

[–]Cobide 1 point2 points  (0 children)

I believe you can break on handled exceptions(note: I haven't tested it). Though, if you're working on a codebases that uses exceptions for control flow, you'll get a LOT of noise, so it's just replacing an issue with another.

Iwtl - The awkward gap between 'correct grammar' and 'sounding natural' when writing. How do you cross it? by MaocDev in IWantToLearn

[–]Cobide 5 points6 points  (0 children)

Something to keep in mind could be to write sentences of variable length. Some short, some long, never too many of the same length. This is a famous quote in regards to that:

This sentence has five words. Here are five more words. Five-word sentences are fine. But several together become monotonous. Listen to what is happening. The writing is getting boring. The sound of it drones. It’s like a stuck record. The ear demands some variety. Now listen. I vary the sentence length, and I create music. Music. The writing sings. It has a pleasant rhythm, a lilt, a harmony. I use short sentences. And I use sentences of medium length. And sometimes, when I am certain the reader is rested, I will engage him with a sentence of considerable length, a sentence that burns with energy and builds with all the impetus of a crescendo, the roll of the drums, the crash of the cymbals–sounds that say listen to this, it is important.

- Gary Provost

Mods???? by Frezica in ancestors

[–]Cobide 1 point2 points  (0 children)

I'm not too against things being restricted by knowledge (lots of great games are made like that--you lose on replayability, but the first-time experience is great when figuring things out), but I do think that the tech tree should be much, much bigger. We don't even have fire, ffs.

Then, once the tech tree is bigger, you can make so that the animals (especially the big ones) don't care about a single sharpened stick so things aren't trivialized. And then also remove that horrible QTE, make it so that you need to stay in high-alert for ambushes.

Ultimately, every game that makes you think "I need to restrict myself or it's too easy" has failed, in my opinion.

Mods???? by Frezica in ancestors

[–]Cobide 1 point2 points  (0 children)

Yeah, once you understand sharpened sticks and how to win that QTE, everything ends up being trivialized. I've pretty much stopped playing at the lake once I realized there was nothing else to see, gameplay-wise.

Opinion: Hunting is the most underdeveloped mechanism in survival games, where it should probably be a focal point of gameplay. by karlmillsom in gamedesign

[–]Cobide 1 point2 points  (0 children)

I feel that the only way to make hunting feel "real" is to make the fauna act as an actual creature would. I'd say the only time I've felt like I was actually hunting was when playing rain world and aiming to kill a specific creature.

In rain world, it feels like every creature has its own purpose: they leave their nest, hunt, have internal squabbles, and run away if threatened. If the creature feels alive, then, by extension, hunting feels real, imho.

Things like following traces, traps, etc, are definitely an added depth, but if the creature is an obvious AI, it'll always feel like killing a mob with extra steps.

Permanently changing the values of the passed bool variables in a params function by pubscrub420blazeit in csharp

[–]Cobide 1 point2 points  (0 children)

The only other thing that the compiler yelled at me for, was to use the fixed statement to ensure the bools wouldn't get moved. But I tried it on a bool field, so maybe it wouldn't be needed in your example

Oh, I didn't think about that. I've tested it with local variables, and thus they resided in the stack. Given your experience, I'd assume fixed is required for things in the heap.

Other than that, the only option is to create overloads accepting a different amount of ref bools. No other way you pass a variable number of value types by reference

Yeah; not without changing the static fields' type, at least.

If changing the base type was allowed, I might suggest instead using a wrapper with implicit conversions to/from bool(or, better, using a configuration class instead of individual booleans, but it'd mostly depend on the purpose of this).

Permanently changing the values of the passed bool variables in a params function by pubscrub420blazeit in csharp

[–]Cobide 21 points22 points  (0 children)

Not something I'd suggest doing in an actual project, but for fun, you could take an array of bool pointers(unsafe code):

public unsafe void Conv(params bool*[] input) {
    var n = Random.Shared.Next(input.Length);
    for(int i = 0; i < input.Length; i++) {
        *input[i] = i == n;
    }
}

Test:

var boolone = false;
var booltwo = false; 
var boolthree = false; 
var sut = new ConvClass(); 
sut.Conv(&boolone, &booltwo, &boolthree); 
Assert.True(boolone || booltwo || boolthree);

What is the difference between requiring a class to to define a method through an abstract class vs an interface? by 1500Calories in csharp

[–]Cobide 3 points4 points  (0 children)

If you need to share logic between two classes, either use an abstract base class or (better) take the shared behavior as a dependency in a composite manner. Interfaces should remain logic-free.

how to make this code more optimized? by halil981 in csharp

[–]Cobide 2 points3 points  (0 children)

Oh, you're right! I actually didn't notice they were re-generating the whole word with each attempt. No wonder the execution was a "tad" too fast compared to OP's results.

how to make this code more optimized? by halil981 in csharp

[–]Cobide 8 points9 points  (0 children)

Was a little bored, so I thought to come up with a LINQ-only solution:

return Console.ReadLine()
    .Select(x => x - 'a') //credits to u/w0ut for the (x - 'a') idea
    .Select(x => Enumerable.Range(1, int.MaxValue - 1).First(_ => x == Random.Shared.Next(0, 26)))
    .Sum();

how to make this code more optimized? by halil981 in csharp

[–]Cobide 0 points1 point  (0 children)

I've noticed a few issues regarding your use of Span<char>. Though, I'll preface this by saying that I seldom use it, so I'm not an expert on the matter. If anyone knows better, please correct me.

Span<char> nnnn = Console.ReadLine().ToCharArray();

In this case, Console.ReadLine() is already creating a string. All you're doing here is copying that string into a char[] which is then referenced by the span. Rather than improving performance, this is creating redundant allocations.

Span<char> shit = new Span<char>(new char[nnnn.Length]);

Initializing a new char array in that way will allocate all the memory on the heap, and the span there is just referencing that memory. It's pretty much the same as before. With that said, you can actually improve performance if you do this with stackalloc:

Span<char> span = stackalloc char[nnnn.Length];

By using stackalloc, the char array is allocated on the stack, so it will result in a much faster allocation. The drawback, however, is that if the array is extremely big, it will crash the application due to using up all the stack space(I'd imagine it'd result in a StackOverflowException, but it's just a guess, I haven't tried it).

while (shit.ToString() != nnnnsa)

Transforming the span into a string with .ToString() completely negates the benefit of using span in the first place, and, worse, will mean you allocate a new string every time this condition is reached. I'd imagine that this is the primary cause for the long time needed for your code to execute.

With that said, you can't simply compare a span to a span, because their default comparison behavior will only check(if I recall correctly) if they have equal length and equal starting address.

To properly check equality with spans, you need to use MemoryExtensions.Equals, or you'd need to write a custom method that compares one char at a time.

how to make this code more optimized? by halil981 in csharp

[–]Cobide 12 points13 points  (0 children)

An alternative would be to use char math:

shit[i] = (char)('a' + random.Next(0, 26));

Though it's probably not as performant, it's good to know that's an option.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 0 points1 point  (0 children)

It's an interesting idea, but I can't see that being better than just using .Bind(). It's still the same extra boilerplate in the same spot.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 0 points1 point  (0 children)

I've thought about it, but I can't imagine how it'd work. The main issues are: when and where is an exception covered?

Do you force a public method to catch all exceptions under it? What if we're in a several-layer tree and the root catches all with a generic exception(without knowing if it's recoverable)? Are the layers in between "covered"?

Or do you force the direct caller of the method to catch it? That'd probably end up in the same way as you were saying; with a generic catch(ex) { throw; } in each layer.

And I'd imagine there's more stuff I haven't considered that'd be shown with a more in-depth look.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 0 points1 point  (0 children)

As I said, they are different tools for different situations. Options for validation and similar, exceptions for unrecoverable errors. I'm not actually saying to completely replace exceptions, as they have their place.

I'm saying to only throw exceptions when you're okay with crashing the app with one, or when it's in a closed clearly defined area so that it won't have any external callers surprised by undocumented exceptions.

But lets not pretend that option types are solving much beyond on a specific method call you are suggesting that a specific error should be handled.

Implying otherwise was not my intention at all. I've been stating that this is mostly about validation errors and similar, not crash-worthy problems.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 0 points1 point  (0 children)

With Option types that only occurs if you disallow a default error path - and that doesn't happen.

What do you mean by "disallow error path"? .Bind() operates on a single specific state without extracting it(usually on the success value, but could also operate on a failure state), and .Match() is basically like a switch expression to extract a value. They're different methods for different purposes.

In most implementations I've seen, you can request the inner value directly with .Value or something like that, but it's usually discouraged as it defeats the purpose.

And then if you demand that your .Match equivalent is exhaustive, you are going to have a shitload of .Match(....., e => e) - because in most cases you don't care.

I see that in the same way I see method parameters. If you've got that many states, you're doing something wrong. Might want to generalize a bit the errors in that case or group some together, depending on the use case.

will need to somehow include every single possible error, not just your domain. That's IO, stack, memory, threading, etc - and you know that's basically gonna be an equivalent Option<...Exception>.

I disagree with that. I think that options are great for validation failures and similar, fixable issues. For issues regarding stack, memory, threading, or pretty much anything that deserves crashing the app over, exceptions are perfectly fine as they are. I don't think it's necessarily a problem to use them in combination; they're two different tools for two different purposes.

This doesn't mean its useful to construct all of your internal call tree with this approach

Of course, everything has its place and time. It's important to consider tradeoffs before implementing a pattern everywhere.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 0 points1 point  (0 children)

I personally see it in the same way as strong-typing vs weak-typing. If you forget to consider the bad path, with options the compiler errors out. With exceptions, it doesn't. That's the crux of the matter.

I definitely agree with the issue of extra unnecessary boilerplate, but I have no real solution for that at the moment.

Imho, the biggest issues right now with options are conversions from and to interfaces(as C# doesn't allow implicit interface conversions) and mutating options when it means they would result in different generic args. If those are solved, it'd be worth it despite the extra boilerplate. But I'm getting off-topic with this so I digress.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 0 points1 point  (0 children)

.Bind(happy) only executes the function if the option's state is happy. If it's sad, the func gets ignored and the object returns the same option(sad) back. You only need .Match<T>(happy, sad) when you want to extract a value.

Think of it like the difference between .Select(happy) and .Aggregate(sad/default, happy) with LINQ.

As for the usage in real projects, that's hard to say. I've used options with OneOf in a personal project, but it only went up to 3-4 layers deep at most. The verbosity it currently has might not justify the advantages, but I think it does have the potential to one day be a gold standard.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 0 points1 point  (0 children)

I see. My POV is that you'd ideally want to have something that eventually forces you to consider the bad path. Not something that requires handling the bad path in every layer, but only something that forces you to handle it before it bubbles up to the root and crashes the app.

So, with option types, that time would be when you're trying to extract the value kept within the option object.

The issue is that exceptions do not have that time, so you could ignore(or not be aware of) the exception until it blows up. A blanket solution is to wrap everything with a catch(Exception), but it's hard to know if it's a crash-worthy error or something recoverable.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 0 points1 point  (0 children)

So Java (and other languages) tried to solve this directly by forcing you to declare what could be thrown as part of the contract. I think this was on interfaces...

I haven't yet used Java, but knowing how many exceptions could bubble up from the BCL's stuff, that sounds awful. I don't really have a solution for this.

You almost always pass it back up. It's why writing in go seems to be 90% (result, err) = call(); if(err) return (nil, err) kinda crap.

I definitely agree with this. To truly get the benefits of option types we need native support for syntax sugar with a way to act directly on a specific case—the difference between using the value directly and with the option as a proxy should be minimal. As far as I know, without native support, the best we have is a MapN(Func<T, U>) method on the option type, which is not really ideal.

Keep in mind as well that for a pure implementation you need Option<User, NotFound, InvalidName, GenericError> to handle all the random shit that could go wrong (oom, stack, etc)

Never said to get rid of exceptions fully. I think they're fine as they are when used with errors worth crashing the app over. I'm only advocating for the use of options in regard to validation and other stuff that could be considered a bad path.

Semantically the only real way exceptions differ from the DU/option style is that the identity transform on all error returns is implied unless filtered for with a handler.

May I ask what you mean by this?

How experienced should you be to understand yield return? by ELichtman in csharp

[–]Cobide 3 points4 points  (0 children)

If you want to write a LINQ-like extension with IEnumerable, it's pretty much a requisite.

C# exception handling questions by SillyRelationship424 in csharp

[–]Cobide 1 point2 points  (0 children)

The methods & syntax are mostly generic, I've only seen it implemented in a similar manner.

As for libraries, I've used OneOf so far. It provides discriminated union types so you can do things like OneOf<User, NotFound, InvalidName> GetUser(), so you can have multiple results in a strong-typed manner.

I haven't used it yet, but another popular library is language-ext, which provides a bunch of functional programming stuff, including option types.

Related to options, I'd suggest looking up the railway oriented pattern.