Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 780 781 [782] 783 784 ... 795

Author Topic: if self.isCoder(): post() #Programming Thread  (Read 813766 times)

mko

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11715 on: April 09, 2020, 06:04:10 pm »

Initial graphics are finally finished in my village/city history simulator! 3D terrain mesh (made with low quality terrain shape generator) with some (low quality) texture are finally working!

Now it is time to start working on simulation so that moving entire mountains and placing houses on top of mountains will no longer work.

And maybe improve terrain, rivers are not supposed to be a straight line.

Spoiler (click to show/hide)

Again thanks to Reelya for mesh code.
Logged

bloop_bleep

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11716 on: April 09, 2020, 07:22:24 pm »

For JSON there is RapidJson, and simdjson for some insane vectorization (might not reach its complete potential on your system, but it supports different levels of vectorization capability.)

For Lua interface there is sol3, which is a pretty nice C++ wrapper for the Lua C API. You could also try using the Lua C API directly. For Schema interface there's Guile.
Logged
Quote from: KittyTac
The closest thing Bay12 has to a flamewar is an argument over philosophy that slowly transitioned to an argument about quantum mechanics.
Quote from: thefriendlyhacker
The trick is to only make predictions semi-seriously.  That way, I don't have a 98% failure rate. I have a 98% sarcasm rate.

MorleyDev

  • Bay Watcher
  • "It is not enough for it to just work."
    • View Profile
    • MorleyDev
Re: if self.isCoder(): post() #Programming Thread
« Reply #11717 on: April 10, 2020, 09:26:31 am »

My advice would be that the important thing with threads is to stop coding in terms as threads as quickly as possible. They're a low-level concept so you need to abstract them away to stand a chance of reasoning about the system. Kinda like Assembly in that sense.

What the problem comes down or is there are four types of data access:

Shared Immutable Data - Inherently thread safe
Shared Mutable Data - Unsafe and needs locks
Local Mutable Data - Inherently thread safe
Local Immutable Data - Inherently thread safe

The only thing that requires thread-safety is shared mutable data access. Which requires locks which are slow since they basically throw away the entire point of multiple threads for the lock duration. And the overhead of locking can actually be slower than just being single-threaded.

So the trick to easier multithreading is to use patterns that require as little shared data access as possible. Immutable data structures, thread safe queues for communication between components, that sort of thing. C++ isn't built from ground up for this sort of thing, so there's a need to either pick libraries or write your own implementations.

The benefit is that shared data access is basically global variables no matter how you abstract it away, so there are code cleanliness reasons to minimise it before even getting into the threading potentials.

An example of doing this is to, rather than using a shared mutable structure to store your application state, if you use an immutable structure and only allow it to be updated via an event call (similar to Redux in Javascript) you completely isolate your state changes. When state changes, the new state can then be pushed out via event to anything that cares for it. Using an immutable data structure for this would mean all that gets passed around is a thread-safe pointer to the latest state.

This makes unit testing game state easier, and even allows you to build some fancy tools that allows for time travel debugging. C++ doesn't have good built-in toolage for this though compared to other languages written later though. Turns out thread-safe immutable data structures in a language without garbage collections is hard.
« Last Edit: April 10, 2020, 10:11:05 am by MorleyDev »
Logged

Telgin

  • Bay Watcher
  • Professional Programmer
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11718 on: April 10, 2020, 07:04:45 pm »

All very good advice, and I'll try to take that sort of approach if / when I actually start the project.

This does bring up the point that if I try to offload much of the game to scripting then it's probably going to be hard to debug those scripts.  That'll be an interesting problem to deal with, but I've got to decide what to hand off to scripts anyway.  Very long term, my vague idea was to have the "story" to be moddable or possible to disable so it's just a sim game, and offload those elements to script.  Starting out, it would just be a sim game as I develop it.  Other stuff like ships, planets and so on would be configurable, and maybe scripting could control the AI or things like that.

I also found out about Chaiscript yesterday, which is designed to be embedded in C++, but it's definitely less mature than Lua.  Maybe I should try both and see how it goes.
Logged
Through pain, I find wisdom.

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11719 on: April 10, 2020, 07:29:13 pm »

"embedded in C++" isn't actually an advantage, it's a disadvantage. If your scripting language is embedded in the code, then you need to recompile the project every time your scripts change. With an external scripting language, you don't have to do that.

That's sort of the point. LUA is every bit as complex as a C-style language and you can implement the entire game in that if you want. But - it won't end up being any easier to understand or debug than doing the whole thing in C++ would, it would just be faster to make changes since you don't have to compile.

The point of LUA is that you can use that to hold data and functionality which it wouldn't make sense to bake into the executable. But if you find yourself using LUA functions to call other LUA functions that have low-level control code in them (if-else, for, while etc) then you've probably offloaded too much of the complexity to the scripts. It would end up a huge mess if you have complex code in both C++ and LUA that you need to juggle.

You can use the LUA stuff to rapidly prototype new functionality, but once that functionality is working, then the code should probably be migrated into the C++, and you expose a handle to LUA for calling that.
« Last Edit: April 10, 2020, 07:40:01 pm by Reelya »
Logged

WealthyRadish

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11720 on: April 10, 2020, 08:14:44 pm »

You might find to start with that all you need to get going is a good parser for configuration files, rather than a full scripted language like Lua. I've used libconfig on several projects, and have found it to be pretty powerful (my only gripe with this library is that it favors error handling through exceptions while I personally avoid them).

Here's an example file from the link, supporting things like arrays and array-like collections of heterogeneous data (including collections of collections):

Spoiler (click to show/hide)
Logged

bloop_bleep

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11721 on: April 10, 2020, 09:11:40 pm »

(my only gripe with this library is that it favors error handling through exceptions while I personally avoid them).

Why avoid them? You may have outdated information. Exceptions, in most modern (good) compilers, are almost identically as fast as exceptions turned off, if nothing throws. If something throws, then the performance doesn't matter, since at that point something's gone wrong anyway -- unless you're using exceptions to do your normal control flow, which you shouldn't be doing.

If there's an error in your config file causing libconfig to throw, your concern shouldn't be that your program lost a millisecond or something, your concern should be that your config file is out of whack.

EDIT: Also, shared immutable data often needs special handling too, to make sure it's not accessed before it's available, e.g. with promises and futures (also in the C++ standard).

EDIT 2: I agree with not overengineering the solution with Lua bindings if you don't need them, however.

« Last Edit: April 10, 2020, 09:21:54 pm by bloop_bleep »
Logged
Quote from: KittyTac
The closest thing Bay12 has to a flamewar is an argument over philosophy that slowly transitioned to an argument about quantum mechanics.
Quote from: thefriendlyhacker
The trick is to only make predictions semi-seriously.  That way, I don't have a 98% failure rate. I have a 98% sarcasm rate.

Telgin

  • Bay Watcher
  • Professional Programmer
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11722 on: April 10, 2020, 10:01:30 pm »

it would just be faster to make changes since you don't have to compile.

Ultimately, this is entirely the point.

Really, thinking about moddability is getting way ahead of myself, but that's what I'm really angling for.  To be more specific, I keep thinking about how Stellaris mods work, which are similar to mods for many games, and it's all done through static config files that usually include some very clunky conditional statements that get bolted on and tweaked in ways that make the code extremely hard to understand.  I feel like these would be much cleaner and easier to make or understand if modders had access to a real scripting language that exposed the needed API components so you could express things in code that really should be code instead of configuration.

And, sure, if I really wanted it to be moddable I could always open source it or something, but people are much more likely to deal with Lua than installing something like Visual Studio and figuring out how to compile the program.

Really, the only reason I even mentioned it is because, like multithreading, if it's something you want to support you probably need to consider it from the very beginning.  Making a prototype without it is still probably my best bet.

That said...

You might find to start with that all you need to get going is a good parser for configuration files, rather than a full scripted language like Lua.

This is still true.  Starting with making things configurable is going to be a lot easier than embedding a scripting language, and this does look like a really nice config file format.  I mentioned JSON before since I use it all of the time and it has support in a lot of languages in case I wanted to make a tool to generate it or something, but JSON does kind of suck for manual editing.  HJSON is better since it lets you define it without all of the quotes, but HJSON support is much less common.
Logged
Through pain, I find wisdom.

WealthyRadish

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11723 on: April 10, 2020, 11:46:33 pm »

(my only gripe with this library is that it favors error handling through exceptions while I personally avoid them).

Why avoid them?

It's not a performance consideration or universal avoidance, for me I just find that some code out there overuses them. They make perfect sense when the error is part of a bigger problem with the system that needs to be passed beyond the current scope, or it would otherwise pollute normal operation to include real error handling. But if the programmer throws for something trivial within the function's normal operation, then it's just a bit tedious to have to wrap every throwing function in another call that deals with minor things the original programmer probably could've just made a decision on themselves. It's an advantage that exception-heavy code gives the user more freedom to handle things precisely how they'd like, but there are times where I really don't think it was worth the extra bloat.

In libconfig's case I think the library overdoes it with a few functions, but it also includes many alternative functions that don't throw if the user prefers them.
Logged

MorleyDev

  • Bay Watcher
  • "It is not enough for it to just work."
    • View Profile
    • MorleyDev
Re: if self.isCoder(): post() #Programming Thread
« Reply #11724 on: April 11, 2020, 08:09:54 am »

I'd agree with WealthyRadish here. I'm of the opinion that exceptions are for unlikely/exceptional circumstances, ideally only thrown when a reasonable default response them is the application closes/crashes. They aren't there for handling multiple possible return types for likely behaviour since they're basically just a slightly prettier variant on the goto statement.

In most languages they require you to read and remember the documentation for a function instead of being able to see possible results of executing a function by looking at it's definition. That's messy. That's ugly. That's poor code design. And in languages like Java that force checked exceptions, they still wind up semantically ugly since you have to handle them outside of the main code flow of a function call (again, basically a goto statement).

There are already better patterns for handling unexceptional circumstances with multiple possible returns, so when possible they should be used: The return type of the functional call should encode all possible unexceptional responses. Languages with first-class pattern matching are best for this, but even C++ has data structures like std::optional and std::variant.

If I try to open a file, and that file isn't there, that's not typically an exceptional situation. It's either the most likely or second most likely result of calling that function after all, so using something like std::optional forces the calling code to handle that likely scenario, and documents it as possible in the function call itself.

On the other hand, the file system itself being flat-out broken in a way that renders it inaccessible by your application could be seen as an exceptional circumstance to which the reasonable default response of the application is to panic and close with some kind of error message.
« Last Edit: April 11, 2020, 08:25:15 am by MorleyDev »
Logged

Iduno

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11725 on: April 11, 2020, 08:43:34 am »

So apparently people have noticed our current programming languages have pretty serious issues (fair), and are trying to find a programming language that doesn't have holes. Somehow, I assume as a joke, they have decided COBOL is the best possible language.

Then, as tangents go, Fortran got thrown out as a terrible language because it was around at the same time as COBOL. Fortran is a great language for teaching basic (no capitals) programming, and other times that you need something quick and dirty, and don't expect answers that are 100% mathematically correct.
Logged

MorleyDev

  • Bay Watcher
  • "It is not enough for it to just work."
    • View Profile
    • MorleyDev
Re: if self.isCoder(): post() #Programming Thread
« Reply #11726 on: April 11, 2020, 09:18:40 am »

I imagine the problem is always defining best.

I'd probably have put Erlang forward as a good candidate for 'best' programming language at present, mostly because pretty much everything the techniques used for modern business programming in a many-core many-cpu cloud distributed world are trying to achieve in other languages is stuff Erlang was already doing back in the 80s.

To quote Wikipedia:
Quote
The Erlang runtime system is designed for systems with these traits:
* Distributed
* Fault-tolerant
* Soft real-time
* Highly available, non-stop applications
* Hot swapping, where code can be changed without stopping a system

Of course, it achieves these through immutable data, functional programming, and first-class support for the actor pattern. So you need to have the knowledge to break your problem down in those terms and have a problem that lends itself well to being broken down in those terms.

If you're in a single powerful core world, best is a whole different set of criteria. And if quantum computing ever becomes a realistic scaleable option, I'd imagine the definition of best would change quite dramatically again.
« Last Edit: April 11, 2020, 09:32:34 am by MorleyDev »
Logged

mko

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11727 on: April 11, 2020, 11:00:56 am »

Somehow, I assume as a joke, they have decided COBOL is the best possible language.

I wonder what kind of metric was used in this joke.
Logged

bloop_bleep

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11728 on: April 11, 2020, 11:35:14 am »

Well, yes. Mostly agreed. I did say you shouldn't use exceptions for common control flows. The StopIteration exception in Python, for example, shouldn't be analogously implemented in C++ (though it's more acceptable to be used by Python since Python has a lot of performance overhead anyway.)

But stuff like configuration options missing/unparseable is a pretty serious error, and it makes sense to throw an exception then so the client code can exit the way it would like.

I just assumed that you were talking about performance because that is often the reason when I hear "I avoid exceptions."
« Last Edit: April 11, 2020, 11:38:41 am by bloop_bleep »
Logged
Quote from: KittyTac
The closest thing Bay12 has to a flamewar is an argument over philosophy that slowly transitioned to an argument about quantum mechanics.
Quote from: thefriendlyhacker
The trick is to only make predictions semi-seriously.  That way, I don't have a 98% failure rate. I have a 98% sarcasm rate.

itisnotlogical

  • Bay Watcher
  • might be dat boi
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #11729 on: April 12, 2020, 07:30:43 pm »

Creating a data-driven game (i.e. declaring things in data files as opposed to in code) is a lot of work. The majority of what I've done the past few sessions is writing functions (i.e. regex and switch statements) that turn text files into objects that the game can use.

Despite how tedious and unexciting it is, I have a very clear idea of how my game's information is loaded, stored, instantiated and cleaned up. Much better than writing a few dozen function calls to create every single game entity, which is what I did the last time I was creating a game without something like Unity or Game Maker to help me.
Logged
This game is Curtain Fire Shooting Game.
Girls do their best now and are preparing. Please watch warmly until it is ready.
Pages: 1 ... 780 781 [782] 783 784 ... 795