• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Adjacent Object Intelligence

M

MagnusTT

Guest
Hi!

I'm pretty new to the program, and I've been stuck for a few days trying to get this simulation to work. Here is what I'm trying to do:

It's a simulation of birch trees, pine trees, and grass. There is a 4 x 4 grid (16 boxes). The top 4 boxes contain birch tree objects, the bottom 4 boxes contain pine tree objects, and the middle 8 boxes contain grass objects. Here are the rules of the simulation:
  1. If a pine tree is next to grass, there is a 60% chance that it will convert the grass to a pine tree.
  2. If a birch tree is next to grass, there is a 40% chance that it will convert the grass to birch.
  3. If a birch tree is next to a pine tree, there is a 60% chance that it will destroy the pine and replace it with a birch
  4. If a pine is next to a birch, there is a 40% chance that it will destroy it and replace it with a pine.
  5. Pine next to pine doesn't need to calculate, and birch next to birch doesn't need to either.
  6. Eventually the board will be entirely full of either Pine trees or Birch trees.
Drawing attached to help explain.

Since there are no actual collisions happening between the tree and grass objects, I'm struggling with how to have my 16 different objects change states by identifying what is next to them and then running the 40%/60% random chance to see if it converts the object next to it. I also don't want all the calculations to happen instantly, I'd like there to be a delay of say... 10 seconds before each object looks around to do calculations.

Any advice from more experienced programmers on how they would tackle this?

Thanks!
 

Attachments

CloseRange

Member
when calculating a collision you don't have to have it colliding right where you are at.
You can ask the question "is there an object at x, y position?"
you can look into collsion_point on the docs but it's just asking the question above.

So to start, let's look at the delay:
it's really easy to have something occur after so long. Add this to the create event:
Code:
seconds = 10;
alarm[0] = seconds * room_speed
now alarm[0] will be called after 10 seconds. Now you can put your code in the alarm0 event (just make sure to add this to the top of the alarm event)
Code:
alarm[0] = seconds * room_speed;
now alarm0 will be called every 10 seconds indefinitely.

if you want to check adjacent objects collisions you want something like this: (again in alarm0 event)
Code:
var size = 100;
var left = collision_point(x - size, y, obj_grass, false, false);
var right = collision_point(x + size, y, obj_grass, false, false);
var up = collision_point(x, y - size, obj_grass, false, false);
var down = collision_point(x, y + size, obj_grass, false, false);
var grass_neighbor = left || right || up || down;
in this size is how big each object is ( i used 100 pixels as an example ) and variable grass is just weather or not there is a neighboring grass object.

in the create event add this line of code:
Code:
randomize();
this randomizes the seed variable allowing you to make random decisions (such as 60% chance of something happening)
now back to the alarm code we can do something to the grass:
Code:
var chance = 60;
if (grass_left && random(100) <= chance) {
    instance_create(x - size, y, obj_pine);
    with(grass_left) instance_destroy();
}
the chance variable stores the 60% chance you wanted, then to decide weather or not to execute the command we use "random(100) <= chance".
you can repeat this for all of your steps.


side node.
In the future i suggest learning arrays. They are really useful and would have been much better here.
I would have used only used 1 object for the whole project and just used arrays but would have been more work to show you how that would work.
 

samspade

Member
Hi!

I'm pretty new to the program, and I've been stuck for a few days trying to get this simulation to work. Here is what I'm trying to do:

It's a simulation of birch trees, pine trees, and grass. There is a 4 x 4 grid (16 boxes). The top 4 boxes contain birch tree objects, the bottom 4 boxes contain pine tree objects, and the middle 8 boxes contain grass objects. Here are the rules of the simulation:
  1. If a pine tree is next to grass, there is a 60% chance that it will convert the grass to a pine tree.
  2. If a birch tree is next to grass, there is a 40% chance that it will convert the grass to birch.
  3. If a birch tree is next to a pine tree, there is a 60% chance that it will destroy the pine and replace it with a birch
  4. If a pine is next to a birch, there is a 40% chance that it will destroy it and replace it with a pine.
  5. Pine next to pine doesn't need to calculate, and birch next to birch doesn't need to either.
  6. Eventually the board will be entirely full of either Pine trees or Birch trees.
Drawing attached to help explain.

Since there are no actual collisions happening between the tree and grass objects, I'm struggling with how to have my 16 different objects change states by identifying what is next to them and then running the 40%/60% random chance to see if it converts the object next to it. I also don't want all the calculations to happen instantly, I'd like there to be a delay of say... 10 seconds before each object looks around to do calculations.

Any advice from more experienced programmers on how they would tackle this?

Thanks!
While slightly more advanced, you might want to look up cellular automata. It'll take a little more work, but basically, what you've described is exactly that. I don't know any tutorials teaching it for GM specifically, but the good news is that it essentially is just looping through arrays, so language doesn't matter so much.

The following is a good series for learning it. It's in Processing, which is based off of Java, but he does a good job of breaking it down into the things that actually matter, and again, it's mostly just arrays so even if you don't know Java it should make sense and be easily duplicatable.

Note that this is a series so it would take some watching but it's also just really good and will make you a lot more comfortable with arrays in general.

 
M

MagnusTT

Guest
Thank you both so much for the responses! I see what you mean about arrays, but I will have to study that for quite some time before I can attempt it. The Cellular Automata is something I've never heard of, and I'll definitely check that out. I'm going to try what CloseRange suggested, because that makes sense to me at my novice level. I'll post back after I have it working. Thanks again!
 
M

MagnusTT

Guest
One immediate question I have is about the alarm[0] event... I assume this would go above the create event for each tree, right? What (if anything) would go into the Step event for the trees? The way I'm looking at it, does each tree only have an Alarm event and a Create event?
 
A

arirish

Guest
Since a Step event by its nature runs every step, and you don't have anything that you need your trees to do every step, no, you don't need a Step event.

The Create event starts the alarm, the Alarm event fires the check positions code, and also restarts itself indefinitely.
 
M

MagnusTT

Guest
Ok, here is my code so far. I have only one oak next to one grass in the room to start. This is on the oak object in the alarm step:

alarm[0] = seconds * room_speed;

var size = 100;
var left = collision_point(x - size, y, o_grass, false, false);
var right = collision_point(x + size, y, o_grass, false, false);
var up = collision_point(x, y - size, o_grass, false, false);
var down = collision_point(x, y + size, o_grass, false, false);
var grass_neighbor = left || right || up || down;
var chance = 60;
if (grass_left && random(100) <= chance)
{
instance_create_layer(x - size, y, "instance", o_oak);
with(grass_left) instance_destroy();
}

but when I run the game, I get this error:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Alarm Event for alarm 0
for object o_oak:
Variable o_oak.grass_left(100003, -2147483648) not set before reading it.
at gml_Object_o_oak_Alarm_0 (line 11) - if (grass_left && random(100) <= chance)
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_o_oak_Alarm_0 (line 11)

So it seems like the variable for grass_left isn't setting properly. To test this out, I added
var grass_left = false;
var grass_right = false;
var grass_up = false;
var grass_down = false;

And when I did so, I didn't get the error, but the script does nothing (which is expected). Any idea why that error is coming up? The script looks correct to me.
 

FrostyCat

Redemption Seeker
That error is coming up because the variable name is wrong. You have left set instead of grass_left. If you're going to come up with your own convention, follow it yourself.
Code:
var size = 100;
var grass_left = collision_point(x - size, y, o_grass, false, false);
var grass_right = collision_point(x + size, y, o_grass, false, false);
var grass_up = collision_point(x, y - size, o_grass, false, false);
var grass_down = collision_point(x, y + size, o_grass, false, false);
 
M

MagnusTT

Guest
That error is coming up because the variable name is wrong. You have left set instead of grass_left. If you're going to come up with your own convention, follow it yourself.
Code:
var size = 100;
var grass_left = collision_point(x - size, y, o_grass, false, false);
var grass_right = collision_point(x + size, y, o_grass, false, false);
var grass_up = collision_point(x, y - size, o_grass, false, false);
var grass_down = collision_point(x, y + size, o_grass, false, false);
Oh!! Thank you, I see what you mean. Yes, this works now. I had never used this type of variable set up before, so the "var grass_neighbor = left || right || up || down;" part threw me off. Thanks again!
 
Top