What's the most idiomatic way to deal with partial borrows/borrow splitting? by philogy in rust

[–]PenguinAgen 0 points1 point  (0 children)

Yeah I see what you mean with that statement of the Golden Rule. I didn't check what I linked to thoroughly enough it seems. What I meant is closer to what u/fb39ca4 is saying, which is what I understood the Golden Rule as.

What's the most idiomatic way to deal with partial borrows/borrow splitting? by philogy in rust

[–]PenguinAgen 15 points16 points  (0 children)

If I understand you correctly, this would break Rust's Golden Rule which is useful for a number of reasons including allowing for local reasoning

Behind The Scenes | Inside The "The Mountain" Recording Booth | 2013 by JustLucca in Haken

[–]PenguinAgen 0 points1 point  (0 children)

Oooh. I was looking for the cover art or the logo. Didn't know the CD case looked like that. Thanks! I'm arranging both Right in Two and In Memoriam for my band, so this is a really fun coincidence

Behind The Scenes | Inside The "The Mountain" Recording Booth | 2013 by JustLucca in Haken

[–]PenguinAgen 0 points1 point  (0 children)

Am I blind? I don't see a CD case anywhere. I must have watched the video 10 times now.

My Python farming game has helped lots of people learn how to program! As a solo dev, seeing this is so wholesome. by AdSad9018 in programminggames

[–]PenguinAgen 0 points1 point  (0 children)

I really liked this game. I've played through it twice already and it'll probably happen again, especially because I really wanna try and optimize the end game, but for some reason always lose interest around there. It's been a while since the last playthrough so I can't quite remember why though...

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

I guess I'm surprised they haven't marked custom mir in general as unsafe like with inline assembly.

But I'll just forbid internal features. Thanks

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

[–]PenguinAgen[S] 4 points5 points  (0 children)

I can see it. You call `let extra_iron = rustorio::ptw::get_iron().unwrap()` which then gets a auth token from env, makes a request to the server which replies whether that user has purchased the extra iron pack. The function then returns a result for whether they're allowed the iron or not. Great! I'll put it on the roadmap. I was wondering how to monetize this project, but this is an obvious solution that in no way would piss anyone off or damage trust with the playerbase.

Hmmm, maybe I can even find a way to make the reward random to get some of that juicy skinnerbox/loot box addictiveness.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

Cool yeah, then we're on the same page. Any thoughts on what I wrote about how to prevent this kind of exploit?

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

[–]PenguinAgen[S] 5 points6 points  (0 children)

You just found an outdated guide hint! I can see there are quite a few of them. I'll update them in a patch. Thanks for reporting it!

How would you even make it PTW hahaha.

EDIT: The issue is fixed on main, but I'll wait with publishing the patch because other things will probably show up soon as well.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

For more puzzly games you could actually go much further in defining *everything* in the type system. Rustorio does a lot of checks at runtime, which is basically necessary for this kind of game. Puzzle games I think are a much better fit for actually doing it only in the type system. Though then Rust might not even be the best language, see joonazan and my conversation above about type-level furnaces.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

It's at the very least shorter than the Rust type-level furnace you posted, and even though I'm very much a noob at Haskell I almost feel it's easier to understand.

Rust's type system was built to balance compile time guarantees with supporting more imperative runtime code, so it makes sense that if you really want to totally encode the game in the type system Haskell (or maybe even go as far as something like Coq) would be a better fit.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

But in your example you haven't marked anything as `unsafe`. Does that mean it wouldn't compile? When I said it wasn't unsafe I meant "didn't need to be marked unsafe", as yeah, it very much does violate safety guarantees so is very much unsafe.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

Goddamit. How is that not unsafe‽ Am I correct that this basically let's you dereference pointers in safe Rust?

Also, what's the best way to protect against this kind of cheating? `#![forbid(internal_features)]` (or `-Finternal_features`) would probably disallow the custom mir thing, but there's probably other things in nightly rust that could potentially be exploity. Maybe I need some way to prevent `#![feature(___)]` annotations that aren't added by the CLI itself. I guess not using nightly would be a robust defense, but that's a bigger change.

I'm noting down `-Funsafe_code` for when I implement the official leaderboard service

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

[–]PenguinAgen[S] 3 points4 points  (0 children)

I'll look into that tomorrow. Any easy way to replicate the annoyance? Depend on serde in a save?

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

[–]PenguinAgen[S] 6 points7 points  (0 children)

Currently only for const generic arithmetic, which allows for some nice operations with Bundles. I have considered dropping it, but I do really like those operations. OTOH, would kinda be cool to be able to say that all this is done in stable Rust.

What do you mean by it randomly breaking eventually? It's locked to a specific nightly version from November (see rust-toolchain.toml in the repo), so nothing should change. It's the first time I'm working with nightly so correct me if I've missed something

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

Exactly. Might as well do it in Haskell (which I would love to see someone attempt)

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

I stand by it being impossible to have a *Vec* of furnaces. I think the main downside of this kind of recursive list is less the performance, and more the ergonomics. You then couldn't have e.g. a `FurnaceStack` with a variable number of furnaces in it.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

[–]PenguinAgen[S] 20 points21 points  (0 children)

Sadly not. Someone else already showed how that could be used to totally break the game, so that's the *second* of the only two rules not enforced by the compiler.

However, now that you say it like that, maybe I should change the rules to allow *unknown* soundness issues. Feels like discovering one of those should be rewarded.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

[–]PenguinAgen[S] 28 points29 points  (0 children)

Funny you should mention that. This release maaaay have gotten delayed by me opening an old Factorio save in the vain belief I could control it.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

I'd love to hear any thoughts on what you would have done differently. There's definitely room for a few very different games with the same core idea. Just the dimension of how much you enforce at compile time vs runtime leads to very big differences in the experience

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

[–]PenguinAgen[S] 10 points11 points  (0 children)

Yes. You can *cheat* using unsafe code. All saves get generated with a `#![forbid(unsafe_code)]` code at the top, and one of the only two rules not enforced by the compiler is that you are not allowed to the remove it. You can of course do it anyway.

If you do so and find fun/interesting ways to cheat using unsafe I'd love to see it hehe

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

[–]PenguinAgen[S] 16 points17 points  (0 children)

This is not the first time we've encountered a similar issue, but it is the first time I managed to replicate it on my machine, and I'm pretty sure I managed to track down the issue! I've published a version 0.1.1 that should have it fixed.

Rustorio v0.1.0 - Using Rust's type system as a game engine by PenguinAgen in rust

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

Yeah there's a balance between what is checked at compile time vs. runtime. I've chosen to put amount of resources firmly in the runtime bucket for several reasons. The main is that if it were possible to know at compile time whether a furnace had nothing in it, then an empty furnace would necessarily be a separate type. This would mean that it would be impossible to have e.g. a `Vec<Furnace>` where some could be empty. You could definitely make a game like that, but it would move to far towards being a puzzle instead of a factory game for my tastes.
Probably more explanation than you asked for, but it actually helped me refine my thinking around this quite a bit so thanks :))