Arsonide's Forum Posts

  • Construct Community - You're my only hope! Well...I mean not really...but you could really help out. Not to mention have custom names ready for your game right when MUSE is released. The syllable based name generator is complete for MUSE, and it loads from files called "syllable sets". I have created a toolkit to help you make these. The toolset includes a python script that will do all the dirty work for you, a couple of example scripts, and also a very early version of a MUSE application that will let you test your syllable sets. I'm going to straight up copy the readme file here. If any of you have any questions at all, please reply with them.

    [quote:3v8737bf]This should help you generate syllable sets for MUSE. I'm releasing it early so the community can contribute sets while I finish the actual plugin. MUSE will actually ship with two name generator actions. One will load from these syllable sets, and another one will generate letter by letter from a set of rules you define. Right now I only have the syllable generator, and I need your help making syllable sets for it! I've made these sets as easy for you to make and test as I possibly can.

    To use the Syllable Set Generator, simply fill the text files with your syllables - either put each one on a new line, or separate them with spaces, the generator can detect either or. Then double click Syllable Set Generator.py when you are done. The python script will automatically populate syllables.ini with your chosen syllables in a way that Muse can understand.

    A prefix and suffix are attached to the beginning and end of the name if you have any defined. First appears first in a name, last appears last. Middle can appear multiple times, between the minimum and maximum middle numbers. Then of course you can have a name generated more than once between the prefix and suffix if you like.

    For examples of first/middle/last: Bo rai cho. El yn dor. Or you can just skip the middle one: Blood letter. Lake wood. Say you wanted to turn that into a modern city district - add a suffix: Lake wood Heights. There's plenty of flexibility here. It's all up to you to flesh it out. I'd appreciate if you guys would post your sets on the MUSE forum thread when you make them so I can get a repository going for the release of the plugin. I already have a TON of sets...but this is something that can only grow larger.

    If you are still confused, I have included examples in the Examples folder. These are example syllable sets. I found most of them on the internet. You can make your own and test them with the Syllable Set Tester, or you can find them on the internet and add them. It's up to you. The Syllable Set Tester is also in this folder. It is a very early version of Muse, and it uses syllables.ini to generate names from, so rename anything you want to try out and move it to this directory under that name if you would like to try something with the tester. I have elven male loaded by default.

    Anything you make and upload to the forum thread is automatically attributed to you. When you run the python script it will ask you for your name, which is embedded into the syllable set automatically as a comment on the top line. Any syllable sets uploaded between now and the release of Muse will be included in the original release.

    Download the Syllable Set Generator!

  • The grid seed is dependent on the root seed, and the data type "fudges" it a bit, so the hash itself isn't dependent upon the root seed, but after it fudges the grid seed, the result is. Technically. The hash is generated at runtime when you poll for data.

    With Void Runner I found myself defining a bunch of constant variables simply to reference the TYPE of data I wanted from the tree. So the start of every file would look like this:

    #define PLANET_EXISTS 0
    #define PLANET_TYPE 1
    #define PLANET_DEFAULT_COLOR 2
    #define PLANET_WATER_LEVEL 3
    [/code:2ab29jsv]
    
    ...and so on. These were then used to "fudge" the grid a bit, by modifying the Mersenne Twister slightly. The data type is to prevent you from needing to do something similar to this with variables in Construct - while at the same time making your data easier to read.
  • GridTree.PollGrid(Name, X, Y, Data Type, Max)

    Sorry, but I'm somewhat confused at whats going on with the expression.

    I get name, and x,y... although an x,y for every x,y is blowing my mind, but Data Type needs a bit more of an explanation.

    The Data Types "BubbleX", and "ColorR", etc, are um, I dunno...

    Are they labels you made up, or are they undocumented system expressions?

    If they're plugin specific, that's fine, but users need some sort of reference to all of them.

    Thats kind of like loumu's dungeon plug using keywords like wall, and rock without an indication of of value.

    Also, on "BubbleX", isn't that a reference to an object being created within the same action?

    Thanks

    As far as X, Y's within X, Y's goes. That's the nature of the plugin. It's hard to comprehend sometimes, even for me. Just remember that when you Poll Grid you want to make sure that you've set your current position for every grid above the current one. You don't need to set your position on the grid you are polling, because that's what X and Y are for in the expression. Of course it wouldn't hurt to set the position anyway, but for large amounts of polling that might be processor intensive for reasons that would take a while to explain. That's why you can poll along a grid without setting position.

    The data type is specific to the plugin, but it isn't explicit. There is no list of them - you can make up any data type you like. You could set it to "badjfo9a8d789dabfiausd" or " "fnord" and it would still behave the same.

    What that actually is is a numeric seed for a type of data, but to make it easier to understand I had it accept strings. The string is then hashed and the hash is used to seed the data type. So basically it is anything you want it to be, as long as you always use that specific word to reference whatever you are trying to look for. Because that word/string/hash/value is used to modify the GRID seed - which allows you to poll for multiple things within the same grid. Does that make sense? Think of each point in the grid like a set of gym lockers, and the data type is the locker you are selecting. You are not drilling down into the next grid - merely specifying that you are checking out something different on the current one.

    So notice how I poll for R, G, and B, all within the same grid - at the same locations - and with the same maximum values. Since this is persistent - technically R G and B should all be the same number. That's what data type does. You specify a unique identifier for what you are looking for - and that identifier can be anything you like - and it splits your grid up into clones with different sets of data. Pretty nifty eh?

  • Players already have IDs, Raknet uses UDP I believe, and everything in that first paragraph is already in except for the host leaving thing. If the host leaves, the server dies.

  • This is awesome. So we an use this to generate levels?

    Yep, that is one use for it. In Void Runner we use it to do pretty much everything. We didn't call it GridTree back then, but this is the same code that we used for placing all of our sectors, planets, rocks on those planets, cave interiors, buildings...everything. I figured someone else would like to have access to that power, and GridTree was born.

    In the example cap you can generate a screen of colored circles, and clicking a circle will generate a screen of squares. The squares are unique to each circle. If you click the same circle twice you will get the same field of squares. It seems kind of simple until you realize that it is only taking a few events, and that all of this is being done without storing anything anywhere. It's all coming out of the root grid's seed. One number. If you change the root grid's seed, you will get a new field of circles...also with their own square "instances". This is a VERY abstract example of a world map and areas within that world.

    Each grid is two dimensional, but in the example cap I only use one dimension of each grid to show off how flexible it can be. You'll notice that "X Position" is always 0. So the second dimension isn't being utilized.

  • download link dose not work.

    First bug fixed! Hehe. Sorry about that.

  • There's the release - be sure to read the last few paragraphs of the post. I updated them with a little more new information. PLEASE post any crashes you experience.

    Any runtime funkiness can be reported as well, but please only report after you've checked it out in debug mode. Sometimes GridTree will return DEFAULT values if you are trying to reference things that don't exist or something, and this can cause runtime funkiness. This is to prevent your program from crashing, and it can be hard to identify, so if you are having some weird problems, click on debug mode. It'll tell you what's going on. If it does NOT tell you, then report a bug here.

    Enjoy guys! ON TO MUSE! MY PATH OF DEVELOPMENT NEVER ENDS MWAHAHAHAHA.

  • Grid Tree release is imminent. I could probably release it now, but I'm going to spend the night searching for bugs and writing a better, less conversational guide. Also I've noticed releases always tend to go better if I don't do them at 3AM. Probably going to write an example cap as well. The example cap will not utilize Noise. Sorry. The benefits of using the plugins together are great but I want to display GridTree alone on its own merits.

    The first release will probably be very unstable regardless of how much I test it. I want you guys to be brutally honest about any crashes you have. I am trying to make the plugin uncrashable - if you try to access data that doesn't exist yet or something, the plugin will simply refuse to do so. If you have debug mode checked, it will also alert you that you are trying to do something undefined.

    Expect it tomorrowish!

  • Instead of putting "score" in Event 1, place global('score').

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • There are not that many complete titles utilizing Construct, but that is not because Construct is too buggy to facilitate game creation. It's just because the community is relatively small compared to Game Maker or MMF2.

    I suggest checking out TowerClimb. That was made with Construct.

  • Construct Classic is now open source, and there is still a powerful community backing for it - at least until Construct 2 becomes more feature complete. Even after that I'm sure some of the community will stick around due to various licensing and technical issues.

    There are still a plethora of programmers working on plugins and patches for Construct Classic, and more pop up every day.

  • M

    ulti-

    U

    se

    S

    tory

    E

    ngine

    Yet another thing I'm working on. Part of MUSE is much simpler to understand, and part of it is a little more complicated. If you choose to ignore the complex part, is basically a large collection of name generators from scifi, fantasy, and real world cultures. It can also generate the names of several kinds of places and several kinds of objects. Everything from african tribal names to feudal japanese and space faring insectoid races. These random names are seeded as well. All of this is pretty easy to understand, and it's difficult to see why I would want an entire plugin dedicated to this seemingly simple function. That's where the complicated portion of MUSE comes in.

    MUSE is a prose generator. Not that it generates prose FOR you, but it can help. Whereas GridTree can easily help you layout geological things - MUSE can help you easily layout chronological things. You pass MUSE the current time and a seed, and the general period of the data you are looking for. Period is kind of like, how long each portion of this data lasts - weather would be shorter periods, while things like political changes and species extinction would be much much longer. MUSE will then tell you the current state of the world based on the time you gave it. (If it's raining, who is in control, etc.) So say for instance you passed it the REAL WORLD time, then things would happen while you aren't playing the game. While you sleep. Say you passed it the time elapsed since the game started - then the game would pause while it was closed. There are two modes that MUSE can run in in this way - one generates a markov chain of "states", as I explained above, which describe events. The second method is going to output you a list of numbers. Explaining this one will require a picture, since we call it the "falling elevator", and the picture will explain why we call it that better than I ever could.

    The picture is rather large, so here's a link to it. Notice that in the picture, the elevator is as tall as three floors. This represents the list of numbers that MUSE will output to you. As you can imagine, the elevator only travels in one direction, which we call "gravity" but for this example we will call "time", and as it does so, older numbers fall off the top end of the list, and new numbers appear at the bottom of the list. Whereas the first method of MUSE will tell you the state of the world, this could be used for a list of entities that come and go. You can even ask MUSE how old an entity is by seeing where on the "elevator" it currently is. So if these numbers represented NPCs for example, the ones near the top of the list would have more gear since they've been in the world longer.

    You can explain them disappearing from the list however you wish. In Void Runner our ships have a small chance to appear as wrecks on planetary surfaces rather than ships if they are on the very top part of the list. This creates a story for the player. For most of the ships however, they simply disappear, and the player needs to fill in the blanks. The pilot moved on to another sector, or whatever.

    The main purpose of MUSE is the chronological stuff allowing you to generate procedural events and histories - the procedural names are icing on the cake. I've been working on it for a bit as a side project. I am working on MUSE and GridTree side by side as my time allows and my interests change - so it is quite likely that both of them will come out at around the same time. I figured this also merited an introduction thread since it will be out around the time of GridTree.

  • The algorithm is imperceptibly fast. However if you are polling it a LOT (such as for every pixel on the screen, in the aforementioned CaveEntrance example), then it's going to be slow no matter what, since you're running two long loops.

    With Void Runner for objects on planets (rocks/trees/etc) rather than poll based on position, we use another one dimensional array. The first number signifies how many objects there are on the layout, and every even number after that signifies an X, and every odd one after that signifies a Y. This is kind of like storing the objects individually in an array rather than storing their positions. It's much faster.

    You could also poll at a set grid rather than at each pixel. (So at every 100th pixel, or whatever).

    I also would love to make it possible to poll a 2D area and have that return an array if possible - but I need to look up how to do that. That would make looping practically unnecessary.

  • I can add that to the description. You don't need to change more than one option with the Adjust actions. You can change one, two, or all of them. I did that so the actions wouldn't get cluttered.

    However, if I group them all into a Tweak section, it won't be so bad. I'll look into that.

  • I've been talking about Infiniscapes and Combobulators and GridTrees now for a long time. Now the plugin is getting close to release, so I figure that I should post a thread. It's not quite ready yet. I'm still trying to make it as user friendly as possible, but for the moment I thought a simple guide on how you can use GridTree to help you generate infinite worlds would suffice as an introductory thread - so here it goes. This might get very conceptual and confusing, so bear with me till the end - it WILL be worth your while. I promise.

    GridTree is a data structure. It is a nested tree of grids that represent data that already exists. You can use this data to create persistent worlds that don't have to be stored in memory. With GridTree you start with a grid, and you choose a point on that grid and move down - and that point expands into another grid. A grid of WHAT you say - a grid of seeded pseudorandom numbers that define what you are trying to represent - be that a small island, a city, a world, a universe, or whatever. This will make more sense as I explain it - I hope.

    The example I'm going to be using frequently throughout this thread is CaveEntrances on Planets. Say I would like to place cave entrances randomly on each one of my planets in my game. There is a 50% chance that at any given point on the Planet layout, a CaveEntrance will spawn. (That's a lot of cave entrances, but bear with me for the sake of example.) There are a lot of planets - and each planet is stored in a System, which in turn is stored in a Sector, which in turn is stored in a Universe. That's a LOT of planets to store - and a hell of a lot more cave entrances! How can GridTree help me out here?

    <img src="http://content.screencast.com/users/Arsonide/folders/Jing/media/39b17d8c-a48b-423c-b630-eccbfaabd83a/2011-05-05_0319.png" border="0">

    When you first create a GridTree - you will be staring at the properties. Here you will define your top grid. The top grid is static, and represents the BIGGEST representation of your area - worlds, universes, etc. The size is how many points are in that grid - so for this example each one of those points would be a Sector. But wait Arsonide! You said this would help me generate INFINITE worlds you liar! Why is the top level sized?! Well, due to memory constraints, we can only poll out for data about 4,294,967,295 in either direction (positive or negative) before things start to loop. Every game has this limitation, including Minecraft. The cool part about GridTree is that you can go down to subgrids to expand your worlds exponentially. In Void Runner our top level is only 100x100, but each one of those points is full of sectors...and each sector full of subsectors. You can keep subdividing it as long as you like in this way. You could theoretically reach the end of the universe, and if you did I would personally send you a cookie, if you hadn't died of old age at that point. Back to the subject - before we can actually read data from a Planet, we need to define all of the grids between where we are now (Universe), and where we want to be (Planet). We do that at runtime with an action.

    <img src="http://content.screencast.com/users/Arsonide/folders/Jing/media/a42d991b-c526-44df-a142-2cf6ea4043b7/2011-05-05_0321.png" border="0">

    You will notice a new term here: "depth". Depth is how far below the top level you are digging into the tree. The only time you ever need to think about this is when you are setting up your grids, but it is pretty self explanatory. Notice how the depth rises as we go down. You can probably guess that our top level (Universe) is at depth 0.

    So now our grids are set up and ready to use! Huzzah! However, before we can pull data from any of the grids below the top level, we have to set our position on each grid. This is very simple to visualize - and is done with a second action.

    <img src="http://content.screencast.com/users/Arsonide/folders/Jing/media/6f1592dd-2cdd-4327-8939-36e106d75bf5/2011-05-05_0323.png" border="0">

    That is your position on each grid. So now we know where we are looking at for every single layer down to the planet. It would read kind of like this: Sector (3903, 390235), System(5, 4), Planet At (5005, 3533), Planet Position: (3356, 3363). Now in Void Runner we actually only use one dimension of System - to define the orbital pattern. So to define each planetary orbit ( [0,1] first from the sun, [0,2] second from the sun, [0,3] third from the sun, etc.) I say that because a grid does not have to be two dimensional if you don't want it to be. It can represent whatever you like. In this particular example those numbers are high because those are the position on the layout that that planet occurs at.

    Now that our positions are set up correctly, we can pull data from any of these grids! Any of them. If we wanted to view a sector map, we could pull a list of all the sectors around the one we are at. If we wanted to check and see if a cave was at a particular position, we would do it like this with an expression...

    <img src="http://content.screencast.com/users/Arsonide/folders/Jing/media/1a462dc4-022a-4d08-995d-43958bf873c1/2011-05-05_0327.png" border="0">

    So at that particular point we check if there is a cave entrance. There is a 50% chance of this occurring. Keep in mind if the player moves up a grid, that you will have to reset positions. polling any grids below the positions you have set will not work.

    So WHY is all of that necessary, you ask. Well some things are just too large to store in memory. GridTree automatically gives each grid its own seed, and every grid seed is based on the one above it...all the way up to the top grid...in this case the universe. That means that any time you come back to a particular planet and check that position - the cave will always be there. You're not storing the entire universe on a hard drive or in memory - you are letting GridTree worry about all of that for you. All you do is set up the grids, maintain your positions on them, and pull data. Your world will remain persistent. If you change the seed, the world will change with it.

    These numbers remain persistent, but what can you use them for? Well imagine that we seeded Noise 2.0's planetary noise with the top level seed of GridTree. At that point we could use the camera position of Noise to poll GridTree for information about things like bushes and trees within each screen on the planet. You could also have a small chance that each screen could have a city in it. Buildings in a city could be their own grid, and GridTree could hand out seeds to each building that designate where the furniture inside that building should be arranged. GridTree seeds could determine the weather of a particular planet, or what sort of animals spawn there, or what factions spawn there and if they are at war - and in that particular planet these things will NEVER change despite being completely procedural.

    GridTree expands your horizons. Alright, this might be a bumpy release, because there is a lot of experimental stuff in this at the moment. Until I'm satisfied with the testing it's gone through, I'm not going to dress it up very much. No readme, just the plugin and the example cap. I'm also keeping this in the Work In Progress forum until I consider it stable, which probably won't be until all of my projects are complete, so expect the WIP forum to fill up a bit. <!-- s:P --><img src="SMILIES_PATH/icon_razz.gif" border="0" alt=":P" title="Razz"><!-- s:P -->

    By the way, if some of you are confused about the "Auxilliary Generator" that is simply a seeded random number generator. It is in no way associated with GridTree, it's just there as a utility.

    I tried to make this uncrashable, but in all likelihood you guys will find ways to crash Construct with it. IF YOU DO - POST WHAT YOU DID HERE. I will fix it. Debug mode is there to help you figure out why things are acting funky for you if they are. Most of GridTree's problems happen at runtime, and if you enable debug mode, it'll pop up messageboxes at runtime telling you what's up.

    UPDATE: I have released a new version of this plugin with some exciting new, slightly experimental options. There are four new actions that will assist you in changing the GridTree. Allow me to explain.

    Imagine you have a grid representing a forest of trees, but your player wants to chop one down. Before, you'd have to keep track of this change the player made, save it somewhere, and overlay it on top of GridTree's procedural data. Now, GridTree can do all of this for you.

    There are two actions: set value at, and revert value at. These actions will ask you what grid you're referring to, what data type you're referring to, and what position you are referring to. If you set the value there, GridTree will now output that value that you set there instead of it's procedural data. This will allow you to "cut down a tree" so to speak. If you want to revert the change, that action is there as well.

    There are two more actions available as well that save the entire GridTree to a file, including all of your manual changes...and another to load this file into the GridTree.

    This expands the possibilities of the plugin quite a bit. I hope you guys like it. There is a new "advanced" example in the zip that shows off these features, with comments and stuff. The example actually is a procedural forest with trees you can chop down. Keep in mind this is still in alpha, but is now back in active development. Please reply with any gripes, complaints, or praise, or bugs, or whatever. It will help me as I continue to develop this.

    Download GridTree!

    Donate!