[Release] BoulderCaves+, a Krissz Engine compatible remake

Everything about the modern clones and remakes.

Moderator: Admin

Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

zsom wrote:Hi.
In anticipation of bouldercaves +,
I decided to install Python 3.10.1 under Windows 10 Home 21H1.
Then Bouldercaves 5.7.2
Everything went well.
However, I did not like the game itself.
I tried both versions of the game, full screen and c64 versions.
I had feelings of slowing down at certain points in the game.
Although I have an i5-8300H processor and 8 Gb RAM and a GTX1050 graphics card.

Also, I couldn't exit the cave by stopping the flashing exit and pressing SHIFT, this doesn't work with Bouldercaves.

Also, I don't know how to run the game with a different set of caves than the standard BD1.

greetings
Hi Zsom,
Yes, indeed, I had exactly the same concerns regarding the original BoulderCaves, and I'm happy to tell you that for the most part, the issues you mentioned are resolved by now :)

The original BoulderCaves doesn't have a true full screen mode as far as I know, it only has a C64 retro mode and a modern tileset mode. BoulderCaves+ addresses this by introducing a true Full Screen mode.

Regarding slowdowns - indeed, the original BoulderCaves wasn't built with optimization in mind, and it could slow down even on a powerful machine. BoulderCaves+ is quite optimized by now compared to the original, even though it still requires an adequately modern PC in order to function at full speed, especially in 60 fps mode, being a Python game. That said, your PC (a Core i5 from 2018, as far as I can tell, with 8 GB RAM) should be more than adequate to run full speed all the time, most likely without any optimization options necessary. Just in case you encounter some slowdowns (which you shouldn't), you can consider trying to run the game through an optimized Python implementation called Pypy3, that'll further boost the fps possible on your PC. But for the record, I'm able to play many caves at full speed without any optimization even on a Raspberry Pi 4 (except for very large or very busy caves with tons of dynamic objects), and a Pi 4 is worse performance-wise than many low-end office class laptops :)

There are many bugs in the original BoulderCaves. For example, you can collect falling diamonds :) Or you can't snap-activate the outbox, yes. Or, when you snap-activate a cell, you can't immediately change direction - this is actually a game-breaking bug. BoulderCaves+ fixes all of these and many more bugs from the original game.

In BoulderCaves, you need to choose a cave set by specifying a command line option. BoulderCaves+ simplifies this by introducing a graphics launcher where you can select a cave set from the menu.

I'm doing my best to fix the known issues with the original and to make BoulderCaves+ a less buggy and more mechanically correct implementation of the Boulder Dash rule set. As to how successful I am thus far, I guess we'll all see very soon ;)

For now, keep in mind that the original BoulderCaves is no longer a good indication of how BoulderCaves+ is going to play or feel. The project has changed from a simple feature expansion to a pretty thorough overhaul and a partial rewrite. As such, even though visually they still look similar in many respects, internally/functionally they are probably more different than similar by now :) Still, the fact that you could run BoulderCaves, at the very least, ascertains the fact that you will be able to run BoulderCaves+.

- Agetian
Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

Today I'm working on improving Rockford animation synchronization. I believe I'm finally on the verge of properly synchronizing his blinking and tapping animation to the animation cycle, just need to run a few more tests and experiments. My efforts are based on GDash source, with some minor adaptation to fit the Boulder Caves+ code base, hopefully this will allow me to make it quite precise.

Also, I implemented support for several additional BDCFF standard options. For example, standard BDCFF options "AmoebaProperties.waitforhatching", "MagicWallProperties.breakscan" and "TimeValue" can be used as standard variants of the Krissz Engine-specific option names "AmoebaGrowsBeforeSpawn", "MagicWallStopsAmoeba" and "ValueOfASecond". When a Krissz Engine option name is present, it'll take priority. Otherwise, the standard option value will be checked. If neither is found, the default value will be assumed. KrisszConvert will be updated accordingly to output BDCFF standard options when e.g. converting to GDash.

In addition to that, I implemented support for the BonusLife cave set property (also BDCFF standard), which allows to define the score points needed to earn a bonus life when not playing in a single life mode. This should make it more feasible to combine Krissz Engine caves into cave sets, since many Krissz Engine caves allow to attain very high scores and 500 points is definitely way too low for a bonus life.

Some more optimization tests may be run today and tomorrow, and after that, I believe I'll be ready to call Boulder Caves+ feature complete for the initial public beta release, and I'll playtest the game for a few more days before making it public.

- Agetian
Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

While making other improvements, I also found some time to implement the redefinable key map. Thus, it's possible to control Rockford not only using the cursor keys, but any other combination of keys that you may like. Sadly, the "snap" action is rather limited - currently only two options are supported (the Control key or the Alt key), the Shift key is very buggy in Tkinter and I decided against trying to make it work with various hacky workarounds. Therefore, for now, snapping can be switched from Control to Alt if desired, but any other key can be used for other actions (moving, pause, start the game).

Here's what the launcher looks like right now (likely to be its final version for the release):

Image

- Agetian
User avatar
CWS
Member
Posts: 429
Joined: Wed Jul 11, 2007 2:32 pm
Location: Austria - Europe

Post by CWS »

would be nice to use xinput, I like to play with my 8bitdo Arcade Stick...
DarkStoorM
Member
Posts: 15
Joined: Tue Dec 14, 2021 10:52 pm

Post by DarkStoorM »

Hi Agetian! First off, sorry you lost access to Krissz website, it was also an accident, I noticed lots of old caves were being played every second, so I just asked Krissz if he was performing some updates on all the caves, but Krissz took it as an attack attempt.

I read this thread and that clarifies everything. Well, things happen :)

Now that we got that out of the way, I was kind of following the forum for some remakes before I registered, but it was not that active - I guess it's just because people don't know about this forum yet :D

I was wondering, are you working on this completely from scratch or you have some point of reference?

I can recommend you a website with a very good portion of Boulder Dash information (not sure how old it is):
https://www.elmerproductions.com/sp/peterb/

Below the Contents there are links that explain "most" of the BD stuff. Some parts are missing, like Slime (haven't looked into other objects).

I used it in my TypeScript Boulder Dash clone, so I did not have any chances of running into bugs with cave objects - the BDCFF Objects specification helped a lot :D

I don't have anything to share myself yet (maybe soon!), but good luck with your release!
Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

CWS wrote:would be nice to use xinput, I like to play with my 8bitdo Arcade Stick...
Yes, indeed! :) I'm eventually planning to switch over from a rather strange choice of Tkinter+Pillow by the original author of Boulder Caves to a more modern and flexible framework such as Pygame 2.x based on SDL 2, that should open up some possibilities to use controllers too when the input is rewired. Might as well look into Xinput and other input methods too.
DarkStoorM wrote:Hi Agetian! First off, sorry you lost access to Krissz website, it was also an accident, I noticed lots of old caves were being played every second, so I just asked Krissz if he was performing some updates on all the caves, but Krissz took it as an attack attempt.
I read this thread and that clarifies everything. Well, things happen
Hi DarkStoorM! Very nice to hear from you and talk to you here, I'm a fan of your work - while I had access to Krissz's, I enjoyed looking through your material! Very good caves! :)
Yes, very true, that stupid incident still gets me. Losing access to the best Boulder Dash game thus far is one thing, but I wish I could at least somehow apologize to Krissz, I actually e-mailed him but I got no response, I don't believe my apology was accepted. That's the worst part about it, to be honest. I didn't intend to do anything malicious, but I fully understand that it looks like I did, and there's very little I can actually do to prove otherwise. But yes, as you said, things do happen... I just wish my thoughless actions didn't affect other people in bad ways, because I understand full well that whatever that stupid downloader did while I carelessly left it unattended made Krissz feel pretty bad and painful, as he believed I was either trying to gain some unauthorized access or find a way to download the caves or something else to that effect :( The fact that he's not responding to me also proves that he does feel pretty bad about the whole endeavor. I most certainly didn't want to be the cause for any stirrup or dramatic events in the community, and well, here I go - I am the cause of exactly something I didn't want to bring about. Quite the irony, heh.
DarkStoorM wrote:I was wondering, are you working on this completely from scratch or you have some point of reference?
I can recommend you a website with a very good portion of Boulder Dash information (not sure how old it is):
https://www.elmerproductions.com/sp/peterb/
Below the Contents there are links that explain "most" of the BD stuff. Some parts are missing, like Slime (haven't looked into other objects).
Thank you so much for this link, it's a very informative read indeed! As for your original question, I have several points of reference: as a starting point, I chose Boulder Caves because it was litreally the only Python BD project in existence that I could find :) Whether it was a good choice or a bad choice in retrospect, I'm actually not sure, since working with it ended up being pretty hard - it's not precise (wasn't made with precision in mind), so a lot of cave scanning details had to be sorted out and tweaked, lots and lots of silly bugs had to be fixed, and the game uses a somewhat dated base framework in the form of Tkinter/Pillow combo for graphics output, which is definitely not the best choice. But as a learning experience, to learn more about Boulder Dash and about Python programming, it was great. The second point of reference was the BDCFF specification and some information regarding Boulder Dash I disassembly bundled with GDash. And actually, the third and possibly the main point of reference was and stiill is the GDash source, which in my opinion is one of the best ways to learn a lot about how a good, sturdy BD clone is made. When it comes to Krissz Engine, my main points of reference were Arno's videos and his cave images that he shared - unfortunately, all of them were cave snapshots, which he took from the cave page in the database, I assume. Those are far less precise than Construction Kit cave image outputs, which is, well... which is why I was trying to find a way ot get those c-kit images, sigh ^^; And while I had access to the game, I experimented a lot in the construction kit, sometimes measuring things frame by frame and comparing them to my implementation. I no longer have that privilege, so I have to go by other sources such as GDash and the videos for details of possible differences.
DarkStoorM wrote:I used it in my TypeScript Boulder Dash clone, so I did not have any chances of running into bugs with cave objects - the BDCFF Objects specification helped a lot
Very excited to hear you're building your own BD clone, and also a pretty unusual one when it comes to the language choice (TypeScript), always nice to see a new clone in a new language! Certainly wish you the best of luck in progressing with this project! Will be happy to play it when it sees the light of day! :)

P.S. Do you mind if I bundle some of your caves with BoulderCaves +? I still have a few convertible pictures saved from the caves I liked, I don't know if I can recreate them in full but Arno's videos should help with that :) As long as you don't mind, of course!

- Agetian
DarkStoorM
Member
Posts: 15
Joined: Tue Dec 14, 2021 10:52 pm

Post by DarkStoorM »

Agetian wrote:P.S. Do you mind if I bundle some of your caves with BoulderCaves +? I still have a few convertible pictures saved from the caves I liked, I don't know if I can recreate them in full but Arno's videos should help with that :) As long as you don't mind, of course!
You can use as many as you want! most of classic-style caves should still be convertible as they use default initial directions for Firefly/Butterfly, so they should be playable :D
Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

DarkStoorM wrote:
Agetian wrote:P.S. Do you mind if I bundle some of your caves with BoulderCaves +? I still have a few convertible pictures saved from the caves I liked, I don't know if I can recreate them in full but Arno's videos should help with that :) As long as you don't mind, of course!
You can use as many as you want! most of classic-style caves should still be convertible as they use default initial directions for Firefly/Butterfly, so they should be playable :D
Thanks a lot for the permission, DarkStoorM! I'll be happy to include some with the first release! :)

- Agetian
zsom
Member
Posts: 84
Joined: Sat Apr 10, 2010 5:46 am

Post by zsom »

Hello
Will it be possible to play bouldercaves + with several Rockfors at once?
There are caves where you have two or more Rockfords from the start.
This is where the "Suicide" key comes in handy.

Regards
DarkStoorM
Member
Posts: 15
Joined: Tue Dec 14, 2021 10:52 pm

Post by DarkStoorM »

Agetian wrote:Another improvement was in the area of object animation speed in general. First of all, object animations are now properly synchronized with each other (thus, diamonds would animate consistently across the cave as opposed to being animated each from a different frame). Second, the speed of object animations now closely matches what is seen on Krissz Engine, though may not yet be completely cycle-accurate and needs a bit more testing. Then again, even if it's not 100% cycle-accurate, I don't think anyone will notice the minimal possible difference except in very thorough, possibly slow motion side-by-side comparisons.
I didn't read the entire thread yet, just cherry-picking while I have some free time. I can give you a hint how I solved the animation problem.

I don't know how would that look in Python, but in JavaScript you can run, let's say, two threads - one that runs in CaveSpeed Per Second and another one in Frames Per Second.

CaveSpeed Per Second is just the Cave Scanning Routine, and then we have a separate thread for Animations, which have to be synchronized for all animated objects (except Explosions, they are separate objects)

The Animation thread just runs in 60 frames per second (just a 1000/60 timeout, separately from CaveScanner), which is a CaveRenderer in my case, it internally increments a global variable (from 0 to 7, then resets to 0 on 8), which indicates an index from the spritesheet to draw for specific object. While drawing a Cave Object in the cave, it first checks that global number and uses it as an index from its spritesheet (all objects have 8 frames of images in one spritesheet), so every object that CaveRenderer is drawing will first look at that global number and pick an image - that way all objects are perfectly synchronized. I ran into this problem with my old Unity (C#) project where Amoeba was completely out of sync, so I decided to have some global index that draws the same image for all animated objects :D

Rockford is a bit different, there are 6 rows of different animations, so each "state" (blink, tap, blink&tap, running, idle) if just switching the "verticalOffset" in the spritesheet and everything works as same as for other objects.

I can show you how the current function looks like for Rockford, according to the object specification (it just returns which row in the spritesheet I'm drawing):
blink and tap variables are global. There is some internal code, but you can get how the general algorithm goes

Code: Select all

public animateRockford(): number {
    let animationVerticalOffset = 0;

    // Called by the animation routine every animation frame
    // If Rockford is currently moving, we display the right-moving or left-moving animation
    // sequence.
    if (caveScanner.rockfordIsMoving) {
      // Can't tap or blink while moving
      this.tapping = false;
      this.blinking = false;

      /**
       * Set up animation left or right as appropriate
       */
      animationVerticalOffset = !caveScanner.rockfordFacingDirection
        ? this.rockfordSpriteOffset.runningFacingLeft
        : this.rockfordSpriteOffset.runningFacingRight;

      return animationVerticalOffset;
    }

    // If Rockford is not currently moving, we display a forward facing animation sequence.
    // Rockford might be idle, tapping, blinking, or both.
    if (game.currentAnimationFrame == 0) {
      // 1 in 4 chance of blinking
      this.blinking = game.globalPRNG.currentNumber % 4 === 0;

      // 1 in 16 chance of starting foot tapping
      // Once Rockford starts tapping, there is also 1 in 16 chance that he will stop tapping
      this.tapping = !this.tapping
        ? game.globalPRNG.currentNumber % 16 === 0
        : game.globalPRNG.currentNumber % 16 !== 0;
    }

    // Switch the spritesheet vertical offset depending on the animation we are about to render
    // this order is important
    if (this.blinking && this.tapping) {
      animationVerticalOffset = this.rockfordSpriteOffset.blinkingAndTapping;
    } else if (this.blinking) {
      animationVerticalOffset = this.rockfordSpriteOffset.blinking;
    } else if (this.tapping) {
      animationVerticalOffset = this.rockfordSpriteOffset.tapping;
    } else {
      animationVerticalOffset = this.rockfordSpriteOffset.idle;
    }

    return animationVerticalOffset;
  }
Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

zsom wrote:Will it be possible to play bouldercaves + with several Rockfors at once?
There are caves where you have two or more Rockfords from the start.
This is where the "Suicide" key comes in handy.
Hmm, I don't think it's going to be quite possible in the initial release, but it shouldn't be too difficult to add that functionality in the subsequent updates. I don't think I've come across caves with multiple Rockfords yet, is that Krissz Engine specific or is it specific to some other engine or just generic? Is there any description of how this should function exactly? (if one Rockford dies, do all of them blow up together, or do you keep controlling the other ones? Which one would be considered primary? I guess I would need a demonstration of the feature and a description of the rules to implement it in my engine :)
DarkStoorM wrote:I didn't read the entire thread yet, just cherry-picking while I have some free time. I can give you a hint how I solved the animation problem.
Thanks a lot for the detailed algorithm, DarkStoorM, much appreciated! :) I believe I'm doing it more or less in a similar way at the moment (though I will look into a couple implementation details soon). The issue I'm facing has to do with the fact that in some cases, blinking doesn't begin with the first frame - I guess it should always do that in case the animation cycle is set to 0 (it's done that way in GDash and in your JavaScript code too), and I can't quite figure out why it's doing that. The code that chooses the animation frame seems a little bit complicated, I think I need to figure out a way to simplify and streamline it in order to make it synchronize the blinking animation frame #0 to the animation cycle #0... :/ It's one of those things when the original Boulder Caves code is doing simple things in a rather complex and roundabout way, and it's difficult to figure out how to rewrite it in a way that won't break other things.

EDIT: I think I found a way to properly synchronize blinking to animation cycle #0, but I still need to turn the blink animation off after 8 frames, otherwise Rockford will just keep blinking again and again :) I'll look into that later, but for now, it works and I think it looks smooth, too.

- Agetian
Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

I'm happy to announce that Boulder Caves+ can now be considered feature complete for the initial release and is now officially in pre-release testing. I'm going to test various modes and interactions and tweak things and fix issues to make the experience more seamless. If I see any opportunities for further optimization of the code, I'll do that as well. I'm also planning to tweak the animation code a little bit more while I'm at it.

Otherwise, things are shaping up pretty nicely and the game should be ready for a release within 7-10 days from now, as originally planned, for Christmas time.

Once the game is released, I'm likely to take a little break from the active development, though I'll still fix bugs and polish the code when able. Then, once another development marathon opportunity presents itself, I'm going to continue working on additional development targets (improving compatibility, possibly adding new requested features such as multiple Rockfords per cave or new objects, or working towards the goal of porting to SDL2/Pygame 2 with controller support and more responsive and modern graphics and input framework).

- Agetian
DarkStoorM
Member
Posts: 15
Joined: Tue Dec 14, 2021 10:52 pm

Post by DarkStoorM »

Things to consider:

(1) writing unit tests - not necessary, but for a good measure or just for practice
(2) game object optimization

-----
(1) In my opinion, setting some base rules for the game to test Cave Scanning Order would be really useful in case you would want to further extend your implementation with new objects - simulate the cave scanning order inside the tests with given cave data to make sure it passes according to some rules.

For example, we have an object like Amoeba and you want to implement some new object, like a variation of Boulder. Now consider the following

Image

Your new object resides at the cell (1), falls to cell (2), amoeba should suffocate and convert into diamonds - test passes
That's just one example, but it would make it way easier to catch potential bugs with new objects
-----

(2) Game Object Optimization:

I don't know yet how your source looks like, but I would definitely avoid storing game objects as... objects, not sure how it works in Python. The fastest way to scan massive caves would be just to store all objects as separate codes. For example, from the link I posted earlier, we can read that: "BoulderDash uses a 6-bit code to represent which object is at each cave position as the game runs".

In my opinion that would definitely make a nice improvement to memory and CPU management comparing to storing everything as objects. It would only increase the number of comparison in some places, but it's still better than storing an entire set of [CaveWidth*CaveHeight] objects. I'm pretty much sure huge cave sizes would not matter with this approach. I haven't tested it out yet in my project, I'm using JavaScript objects myself, but the CPU usage in a regular 40x22 cave will of moving Flies or Rockford collecting mountains of diamonds is just 4-6%, I still need to check 100x100 caves! Storing an array (or List, or a Set) of just object codes should be way more performant than storing an array of objects with different properties.

Time for some more experiments! :D
Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

Thanks a lot for the input, DarkStoorM, those are really valuable and valid points! I agree that unit tests would be nice to automate coverage for things that may break over time as new elements are implemented, to ensure that something that currently works won't break in the future and also to automate testing the new objects in a variety of contexts.

A very good point regarding storing objects - I'm also currently using Python objects in order to store the cave data, something also inherited from the original Boulder Caves, and it definitely creates quite an overhead when it comes to memory usage and CPU processing power needed to work through the cave scan every frame. I'll actually run some tests in the next few days to see if I can switch over to a code-based approach easily enough. For starters, it might even be a straight-up BDCFF [map] code-based representation, where each character would map to an actual object. Then, those codes would be compared first, and if they match, then the object will be evaluated in the context of its properties and whatnot. This should actually be quite critical for a Python program, and could lead to higher performance on pretty much any hardware, including some hardware that is currently borderline or unacceptably slow to run Boulder Caves+.

Thanks a lot again, and I'll keep you posted as to how my experiments go! :)

- Agetian
Agetian
Member
Posts: 78
Joined: Sun Sep 19, 2021 10:14 am

Post by Agetian »

Today I have a question about something that might feel a little bit controversial (and, well, it actually most likely is). Since I'm going to release the game to the world pretty soon, and the game is the first one to feature a certain (pretty high, actually) Krissz Engine compatibility, we need to decide on something regarding how exactly the game is going to ship.

As all of you who are members of Krissz's website know, Krissz Engine actually features several updated assets, mostly based on the original assets by Peter Liepa and Chris Gray. These assets are present in the game itself and can be seen in the various screenshots and videos on this website. Namely, the assets I'm referring to are as follows:

- The second "falling boulder" sound, which appears to be a pitch-shifted and possibly otherwise slightly modified version of the original falling boulder sound.
- The light boulder icon, which appears to be exactly the same as the original boulder icon, but squashed vertically by one pixel. The visual pattern on the boulder is the same as the original.
- The slime icon and animation, which is the same as the original slime, but changed to single color (without the second-color outer rim) to differentiate it more from the amoeba.
- The slime editor icon, which is basically the slime icon with the letter "S" on top of it.
- The inbox and outbox icons, which are the "empty inbox" tile with the letters "IN" and "OUT" written inside.

For my internal testing, as you've most certainly seen from the screenshots, I'm using an updated tileset (and sound set) with those same changes applied. How reasonable would it be to ship them with Boulder Caves+ though? On the one hand, I don't want to step on Krissz's toes any more than I already have. I also have no means of communicating to him, he hasn't responded to me since the whole downloader debacle. Given how protective he is of his material though, he most likely just hates me for doing what I'm doing anyway, tile set or not. I doubt he finds the idea of Krissz Engine getting a "possibly competing" (well, not really, but you get the point) compatible engine a pleasing one. On the other hand, I understand that those rehashed assets mentioned above are, in their own right, just slight modifications to the original artwork by Peter Liepa and Chris Gray, also used without permission by Krissz. So in fact, we're all, in a sense, infringing here - me, Krissz, every other author of a Boulder Dash clone or remake that uses the original game graphics and sounds in their pristine or modified form without any permission... So, I don't know.

That said, it's not a problem to create substitutions for most of these. In fact, I already have a sort of a "demake" for those modified assets, which are my own versions of the tiles, that would not be the same as Krissz's. They look slightly different, but they represent the same things and they're similar in meaning. The only tiles I haven't changed and that I believe are fair game anyway are the light boulder and the slime, since they are, in fact, the original BD1 and BD2 artwork, with a very slight modification that's very difficult to represent in any other way. Well, I can prolly change the pattern on the light boulder a little, but that's about the only thing I can think of. The slime is just a slime. If we want it to look like a slime and be distinguishable in a 4-color palette, we have to remove the rim (I can experiment with other possibilities like adding more colors or changing the rim color, but not sure if that'll look good since Krissz Engine caves are not designed with that in mind and this change may only make them look ugly). And if I keep the original BD2 slime animation, it'll be difficult to distinguish from an amoeba in any Krissz Engine cave which uses a 4-color palette and doesn't have a separate color for a slime and for an amoeba.

So, what do you think? Would you believe that it would be fair game to ship Boulder Caves+ with a tileset modified in a way that look and the sound the same as Krissz Engine does? Or would it be preferable to ship the game with the modified tiles changed in a way that would not be the same as Krissz Engine, but would resemble it enough so that things can't be confused with each other? If we go with the latter course, I most certainly also won't ship the second boulder sound (which I recorded from a gameplay video btw, even before I first got access to Krissz Engine), and the two boulder sounds will just be the same unless someone changes the second one to a Krissz Engine style one or just some different one.

A tricky question, but it needs to be addressed.

- Agetian
Post Reply