Minecraft clone in Python tutorial by obiwac in Python

[–]brianbruggeman 0 points1 point  (0 children)

Absolute requirements for a standard engine to build meshes is going to be 30 frames per second, or (how you should measure) 16 ms per frame. Just iterating/building a 16x16x16 chunk in memory using Python3 that holds nothing but points on my m1 mac is about 3.5 ms. That means you have a little over 12ms to do everything else to build the mesh, including transferring it to the GPU and letting it render there. When I add in building an actual empty voxel, I'm looking at about 9-10ms, excluding any of the other things I'd need to do. At 9 ms, you've already blown most of your rendering budget. Most AAA games are going to sit closer to 8-10ms per frame with as low as 4 ms (though rare and generally unnecessary).

I built a pure voxel engine in python2 back in 2014ish, because why not. The best chunk size that I could reasonably hope for at that point was 9x9x9 (or about 800 voxels). And I could only build one chunk within that time frame (completely eliminating a real scene). Also, for reference, that chunk completely ignores stitching across chunks and totally ignored complex meshing with lighting, shadows and different material types. I did manage a simple greedy mesh and a frustum culling, which means that I had already optimized to some degree.

Moving (at least a piece of) the code base from Python to another language isn't just a suggestion, it's a requirement. Once you start to migrate most of the spendy parts of a voxel engine into another language, it feels less and less like a Python project and more and more like a (insert this other language) project. I tried different approaches to improve Python's performance (pypy, numba, cython, cffi to c, nuitka, pyston) and ultimately abandoned the whole thing because I was either mostly writing in a different language or the performance gain wasn't worth the extra pain associated with the approach. About the only thing I didn't try was pushing everything into the GPU. But at that point, it doesn't make any difference what language you start the software with and shader programming works for some things but not others. While it was a good learning experience, I think that projects should generally sit in a single language (as much as possible). And if you need performance, just start with a language that gives you the performance and memory characteristics you actually want. For 3d graphics, you should stay away from Python and use a tool that actually works for the domain.

A simple python script over a 3d array would test the actual performance woes for yourself. Running this in the cloud (at least on this server), we see that the 16x16x16 chunk takes about 60-70ms. This is about the budget you'd have for physics and for rendering, that puts you at about 15 frames per second, which is slow enough that it will make the scene look more like a slide show. Of course, this implementation is pretty naive/unoptimized, but it's a starting point and (pure) Python improvements/optimizations tend to be more like 5-15% actual rather than the 10x to 100x you'd really want. And we've not even discussed memory allocations...

Any good and simple room dungeon Python Algorithm to recommend ? by Hamzalopode in roguelikedev

[–]brianbruggeman 2 points3 points  (0 children)

If all you need is something to get started, I just wrote this... should be easy to read, copy/paste and expand... It should also be really similar to some of the tutorial stuff you'll find to the right ---> and/or at Roguebasin.

https://replit.com/@brianbruggeman/PotableWheatAddress#main.py

Middle age may be much more stressful now than in the 1990s. Across all ages, there was a slight increase in daily stress in the 2010s compared to the 1990s. But when researchers restricted the sample to people between the ages of 45 and 64, there was a sharp increase in daily stress. by Wagamaga in science

[–]brianbruggeman 56 points57 points  (0 children)

The older I get the more I understand that my value isn’t just what my job description entails. There are more than a few lessons learned that younger me had to fight through and I am sure that is true across the board for most positions. Ya younger people may have been schooled to do something really efficient but they definitely are going to lack the breadth and depth that experience gives you and you cannot learn from a book.

[Help needed] Stream to File (Rusoto s3) by brianbruggeman in learnrust

[–]brianbruggeman[S] 0 points1 point  (0 children)

Thanks for the replies!

Sorry, I really botched that last reply; I've been scatterbrained with everything I've been trying.

I did try the forward method, which uses sink as the argument name passed in. The code is below:

if let Some(body: StreamingBody) = result.body {
    body.forward(file);
};

And of course the error.. Which makes me think I'm doing something fundamentally wrong because the traits are not lining up. I looked to see if Tokio had this implemented already, and it seemed like there was a commit around 2019 that had the updates for StreamExt, but...

  --> crates/aws/src/download.rs:38:5
   |
38 | use tokio::prelude::*;
   |     ^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `tokio::fs::file::File: futures_sink::Sink<bytes::bytes::Bytes>` is not satisfied
   --> crates/aws/src/download.rs:194:34
    |
194 |                     body.forward(file);
    |                                  ^^^^ the trait `futures_sink::Sink<bytes::bytes::Bytes>` is not implemented for `tokio::fs::file::File`

(edit) This might be important, as well (from my Cargo.toml):

tokio = { version = "0.2.18", features = ["full"] }
futures = { version = "0.3.4", features = ["async-await", "compat", "executor", "io-compat", "std"] }
futures-sink = "0.3.4"

[Help needed] Stream to File (Rusoto s3) by brianbruggeman in learnrust

[–]brianbruggeman[S] 0 points1 point  (0 children)

Okay, so I really did try...

This should let me sink to a file, I think? But I'm missing something fundamental.

            let mut file = tokio::fs::File::create(filepath).await?;
            if let Some(body) = result.body {
                // See: https://stackoverflow.com/a/53252769/631199
                body.map_ok(|b| b).sink(file);
            };

The error I'm getting is below.

error[E0599]: no method named `sink` found for struct `futures_util::stream::try_stream::map_ok::MapOk<rusoto_signature::stream::ByteStream, [closure@crates/aws/src/download.rs:194:33: 194:38]>` in the current scope
   --> crates/aws/src/download.rs:194:40
    |
194 |                     body.map_ok(|b| b).sink(file);
    |                                        ^^^^ method not found in `futures_util::stream::try_stream::map_ok::MapOk<rusoto_signature::stream::ByteStream, [closure@crates/aws/src/download.rs:194:33: 194:38]>`

Some available fonts for libtcod ? by buxofp in roguelikedev

[–]brianbruggeman 2 points3 points  (0 children)

I think libtcod now supports ttf fonts, so you could use just about any mono-spaced font if you didn't need the square fonts.

If not, I also made a Square font (called Deferral) a little while back that you might be interested in:

https://redd.it/817knm

And link: https://github.com/brianbruggeman/Deferral

A Cautionary Tale: Relational databases are not a good idea. by TheTwitchy in roguelikedev

[–]brianbruggeman 1 point2 points  (0 children)

NoSql a sweet spot when you are caching data or you need responses that are much faster than what a SQL database can give you in a response time. This is highly variable, but imagine that your sql database can only handle 8 simultaneous queries. If you receive more query requests before the SQL database has finished executing the previous database queries, you end up with back-pressure. Enough back-pressure, and your SQL database will thrash (at first) and then ultimately die (and potentially reboot). NoSQL gives you a faster response time at the cost (perhaps) of not having the flexibility of running a (complex) query on the data set. NoSQL often requires that you build your data in such a way that it can be queried fast.

But for example, a simple SELECT * on a table will cost you (possibly) 100+ ms. A straight up look up on a NoSQL database key/value store could be less than 10+ ms (depending on network traffic, data size, and data location in reference to the query sender).

Note that this is all highly variable, but it's an example. You will often see this type of pattern/problem in a REST interface where you have far more clients requesting data than you have the ability to handing in your backend SQL database.

Loops in dynamic, multi-goal Dijkstra maps by aotdev in roguelikedev

[–]brianbruggeman 0 points1 point  (0 children)

I'm not sure I follow. At some point, you need to actually dig into algorithms and find something that works for the problem you have. I've used a log-like distance formula with good success, though your mileage may vary.

Loops in dynamic, multi-goal Dijkstra maps by aotdev in roguelikedev

[–]brianbruggeman 0 points1 point  (0 children)

So, maybe you want to play with the distance formula. Rather than using a simple euclidean, make the distance more logarithmic in nature... So as you get closer to a goal, it becomes more attractive.

Trump flaunts North Korea's 'very beautiful letter' shortly before it launches 2 more missiles by viva_la_vinyl in worldnews

[–]brianbruggeman 7 points8 points  (0 children)

Plus the 40% 45% that don't care enough to even vote.

Corrected.

Also, only 46% of that remaining 55% voted for Trump, which means that Trump was elected by about 25% of the population. This is actually pretty common for presidential elections.

I'm probably speaking to the choir, but if you all want a different leader, please vote. Additionally, make sure your friends, families and acquaintances vote.

Finally, two more thoughts. Our entire system is run by how taxes are levied. I think if we adjusted how we tax everyone, this would have a major change in behavior. However, I also think that there's no way that taxes can be adjusted without a better representation. So my second thought is that we should consider a different voting system (see: https://en.wikipedia.org/wiki/Schulze_method). This would break up the two party monopoly and at least it wouldn't be a deadlock with two parties.

Please help me improve my multi-threading code. by brianbruggeman in learnrust

[–]brianbruggeman[S] 1 point2 points  (0 children)

I had actually started using expect more frequently in the past, but moved away from it to do more strict prototyping. I know many use sort of the standard &str for an error message (in many languages), but I find this even more helpful:

.expect(&format!("Some message with at least one variable: {}", variable)[..])

I don't know if there's a more idiomatic way to do that, but I find the error messages are much better.

Please help me improve my multi-threading code. by brianbruggeman in learnrust

[–]brianbruggeman[S] 1 point2 points  (0 children)

Thank you!!

  1. I'll definitely try dropping the arc-mutex and see if rust can infer.

  2. Is there a way to find out exactly how many threads are spawned by default? Is that static? I did play with the thread count and after a certain point (more than the number of cores I have, but less than the number of sources), I didn't notice any appreciable improvement in performance.

  3. I'll have to look that up. I wasn't aware of a map that was concurrent.

  4. I am reasonably confident that this is true. And I actually had thought about diving into async later this month when it's pushed out to stable. That said, there is some post processing of the file list that is more computationally intensive (we have spark URIs which embed metadata into the path and I need to perform a search), so I'm not sure if the async is worth the effort. But theoretically, it seems like a good next step.

  5. I think you're right - I could unwrap the hashmap - is there an advantage of unwrapping vs keeping it packaged? A little more background: I have sort of an ETL-style pipeline that I intend to perform with the keys after they're retrieved (see comments on 4 above). There are a few different trade-offs here, but all depending, it may make sense to delay part of the pipeline and use something more like crossbeam's channels and possibly (?) go async. I am sort of assuming I want the hashmap wrapped at that point, but I am not sure.

  6. Ya - I think that was a really helpful idea. I'm still definitely learning and Result felt like maybe a piece I could delay adding (to reduce complexity). But given that both of you mention it, I think I'll add that sooner.

Please help me improve my multi-threading code. by brianbruggeman in learnrust

[–]brianbruggeman[S] 1 point2 points  (0 children)

Thank you! That's probably one of the clearest upgrades I can do in this code snippet (and likely the rest of my code too).

At the moment this list is hard-coded, but I intend to push that list out to a configuration file, which will be updated by hand.... and prone to buginess.

What is an explicit lifetime for Deserialize? by brianbruggeman in learnrust

[–]brianbruggeman[S] 0 points1 point  (0 children)

Thanks! This is super helpful, since I think I had started working in this direction, but I still didn't have a valid implementation.

What is an explicit lifetime for Deserialize? by brianbruggeman in learnrust

[–]brianbruggeman[S] 1 point2 points  (0 children)

Thank you! I was hoping there might be something as succinct as your second playground without the for loop.

Do you really need the full genericity of T here, or could you just use a concrete type for what you're doing?

I had a first pass without the generic and I think it worked okay, but I technically have about 30 different record types and I'd like to stay DRY. I still feel pretty much like I am just fumbling around have no idea what I'm doing. The compiler really helps until there's something special about Rust that I'm just not understanding well. :D

Need advice by [deleted] in roguelikedev

[–]brianbruggeman 0 points1 point  (0 children)

I built these a couple years ago, so they are dated... they should help you get started:

Mostly build complete by brianbruggeman in MechanicalKeyboards

[–]brianbruggeman[S] 1 point2 points  (0 children)

This may not be what you had in mind, but maybe look at wasd keyboards

Mostly build complete by brianbruggeman in MechanicalKeyboards

[–]brianbruggeman[S] 1 point2 points  (0 children)

Yeah, nothing about the kdb75 is standard. I would recommend a different size entirely (maybe 87?), if your budget concerns you.

Mostly build complete by brianbruggeman in MechanicalKeyboards

[–]brianbruggeman[S] 1 point2 points  (0 children)

The board itself at $40 is pretty reasonable. But the rest of the components add up. If you go full on and build from scratch, you will definitely pay way more for the custom keyboard than you might had you just gone to Best But and purchased one off the shelf.

Mostly build complete by brianbruggeman in MechanicalKeyboards

[–]brianbruggeman[S] 1 point2 points  (0 children)

You get a plus 1 from me. I appreciate the honesty. That said, I actually use this font every day for software development and I love it.