Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Katamori

Katamori's programming misadventures - now with videos!

Recommended Posts

I'm back!

i don't want to talk about my plans at the moment, but I'm close to make a cellular automaton system that works correctly.

The problem is that this test automaton works perfectly:

#define fldwidth 55 
#define fldheight 70

//struktúra, aztán a sejtek definíciója

typedef struct tiles{
					unsigned char red, green, blue;
					}tiles;

//sejttípus 1.: tesztsejt: minden magányos sejt meghal
void Test(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
	int a,b,i,j,counter;

	for (j=1;j<fldheight-1;j++)
	{
		for (i=1;i<fldwidth-1;i++)
		{
			counter = -1;
			for (b=j-1;b<j+1;b++)
			{
				for (a=i-1;a<i+1;a++)
				{
					if (arra[a][b].red == 200)
					{
						counter=counter+1;
					}
				}
			}
			//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
			if (!(arra[i][j].red == 200 && arra[i][j].green == 0 && arra[i][j].blue == 0) && counter > 0)
			{
				arrb[i][j].red = 200;
				arrb[i][j].green = 0;
				arrb[i][j].blue = 0;
			}

			if ((arra[i][j].red == 200  && arra[i][j].green == 0 && arra[i][j].blue == 0) && counter == 0)
			{
				arrb[i][j].red = 100;
				arrb[i][j].green = 0;
				arrb[i][j].blue = 0;
			}
		}
	}
}
But my Conway's game of life doesnt. It kills all the cells in the first round, which means that only the second if() condition works. Most strangely, if I use < and > instead of << and >>, even those don't work.
*same beginning: defines, structures

//sejttípus 2.: Conway életjátéka
void Conway(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
	int a,b,i,j,counter;

	for (j=1;j<fldheight-1;j++)
	{
		for (i=1;i<fldwidth-1;i++)
		{
			counter = -1;
			for (b=j-1;b<j+1;b++)
			{
				for (a=i-1;a<i+1;a++)
				{
					if ((arra[i][j].red == 0 && arra[i][j].green == 200 && arra[i][j].blue == 0))
					{
						counter=counter+1;
					}
				}
			}

			if (!(arra[i][j].red == 0 && arra[i][j].green == 200 && arra[i][j].blue == 0) && counter == 3)
			{
				arrb[i][j].red = 0;
				arrb[i][j].green = 200;
				arrb[i][j].blue = 0;
			}

			if ((arra[i][j].red == 0 && arra[i][j].green == 200 && arra[i][j].blue == 0) && (counter << 2 || counter >> 3))
			{
				arrb[i][j].red = 0;
				arrb[i][j].green = 100;
				arrb[i][j].blue = 0;
			}


		}


	}
}
These are just the functions, the main() function works correctly.

Any suggestions?

Share this post


Link to post

Eh?

			for (b=j-1;b<j+1;b++)
			{
				for (a=i-1;a<i+1;a++)
				{
					if ((arra[i][j].red == 0 && arra[i][j].green == 200 && arra[i][j].blue == 0))
					{
						counter=counter+1;
					}
				}
			}
The if-statement uses i and j as indexes, I assume you should be using a and b instead? Because of this the counter doesn't work properly.
if ((arra[i][j].red == 0 && arra[i][j].green == 200 && arra[i][j].blue == 0) && (counter << 2 || counter >> 3))
<< and >> are bit shifts, are you sure you're supposed to be using them? Wouldn't counter != 3 (!= is "not equals") be what you're after?

Share this post


Link to post
Jodwin said:

Eh?
[...]
The if-statement uses i and j as indexes, I assume you should be using a and b instead? Because of this the counter doesn't work properly.
[...]
<< and >> are bit shifts, are you sure you're supposed to be using them? Wouldn't counter != 3 (!= is "not equals") be what you're after?


Later, I could notice both of them and I fixed both mistakes, but the program wtill doesn't work. There is no newborn cells, which means that the first condition still wrong somehow...

Share this post


Link to post
Katamori said:

Later, I could notice both of them and I fixed both mistakes, but the program wtill doesn't work. There is no newborn cells, which means that the first condition still wrong somehow...


That's because you use counter=-1 as a base. An empty cell having 3 alive neighbors will get a value of (counter == 2), hence it will never work. You really need a cleaner way to express "alive cell with 3 neighbors" and "empty space with 3 neighbors".

Also, you REALLY need to use a simpler structure to represent cells than RGB triplets, or at least use struct comparison and assignment instead of doing three-fold comparisons and assigments.

E.g. make a struct:

const tiles ALIVE_CELL={0,200,0};
const tiles DEAD_CELL={100,0,0};
and use something like
if (arra[i][j]==ALIVE_CELL && counter != 0)
			{
				arrb[i][j]=DEAD_CELL;
			}
Actually, I'd decouple the status of a cell from its colour: use something like a status integer instead: negative for a dead cell, zero for a newbord, and +1 for each generation that it survives, with color being an independent property.

Share this post


Link to post

1.)

I have to start with -1 because this:

for (b=j-1;b<j+1;b++)
			{
				for (a=i-1;a<i+1;a++)
				{
					if (arra[a][b].red == 200)
					{
						counter=counter+1;
					}
				}
counts arra[i][j] too, which is unnecessary to add. For example, if there's a lonely cell, and I start counting with 0, the result would be 1, which would mean for the program that the cell has a neighbour, which is false.

Anyway, I did it but the Conway game still doesn't work when the condition of born in counter == 3. But without that, it can't be the Conway's automaton.

2.)

Thanks for the tip, I looked for some simplier implementation for a while. Seriously, I don't know what would I do without you, Maes - on Stack Overflow, if I explain my problems as long as here, I wouldn't get so precise answers!

However, for this code:
typedef struct tiles{
					unsigned char red, green, blue;
					}tiles;


	const tiles TEST_ALIVE = {200,0,0};
	const tiles TEST_DEAD = {100,0,0};


//sejttípus 1.: tesztsejt: minden magányos sejt meghal
void Test(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
	int a,b,i,j,counter;

	for (j=1;j<fldheight-1;j++)
	{
		for (i=1;i<fldwidth-1;i++)
		{
			counter = -1;
			for (b=j-1;b<j+1;b++)
			{
				for (a=i-1;a<i+1;a++)
				{
					if (arra[a][b] == TEST_ALIVE)
					{
						counter+=1;
					}

[...]
Visual Studio gets an error message: "error C2678: binary '==' : no operator found which takes a left-hand operand of type 'tiles' (or there is no acceptable conversion)" which is for "if (arra[a][b] == TEST_ALIVE)"

Share this post


Link to post

Hmmm....my C must be a bit rusty. Indeed, you can do assignments (=) with structs, but not comparisons (==).

http://stackoverflow.com/questions/141720/how-do-you-compare-structs-for-equality-in-c

You must make a comparator function of sorts e.g.

boolean cmpTiles(tiles* a,tiles* b){

// field by field comparison....

}
Still, that's a much more elegant solution than writing an inlined customized comparison everytime you need to compare two tiles!

As for the counter situation, as I said you must check whether the "center" cell is alive or not, before subtracting one from the counter, which should start from zero.

Also, what the heck at this condition:
		if (!(arra[i][j].red == 0 && arra[i][j].green == 200 && arra[i][j].blue == 0) && counter == 3)
			{
....
that "!" after the "if"...this condition only guarantees that a DEAD cell will turn into an alive one if counter == 3 (which ofc, due to the way that counter was updated, would never happen as it should).

An ALIVE cell with 3 neighbors however (which should survive a generation) won't survive with this code, because it fails the first check with the "!", hence a) All of your alive cells die and b) No new cells are born, either (unless they have 4 neighbors so counter == 3...)

Share this post


Link to post

1.)

I use it instead as a different function:

bool equality(tiles& a, const tiles& b) 
{
    if (a.red == b.red && a.green == b.green && a.blue == b.blue)
	{
		return true;
	} else {
		return false;
	}
}
but my test cells still dies without any new born. Why?

2.)

Shouldn't that second code mean that "if the cell is NOT alive and counter is 3"? Because there'll be even much more types of cells, and I don't want "collisions". So I can't get, why only dead cells can turn into alive. Everything else should be able to become alive.

EDIT: I post it on Stack Overflow too, heavily explained.

Share this post


Link to post
Katamori said:

bool equality(tiles& a, const tiles& b)


I'm not sure that passing a struct with the address modifier (&) will work as intended: what the function "equality" sees might not be what you meant at all. I would expect it to be like this:

bool equality(tiles* a, const tiles* b)
and then referencing the various members with
a->red=... ;
a->green=...;
etc.

Also, how do you use/call it?

but my test cells still dies without any new born. Why?

Katamori said:

Shouldn't that second code mean that "if the cell is NOT alive and counter is 3"? Because there'll be even much more types of cells, and I don't want "collisions". So I can't get, why only dead cells can turn into alive. Everything else should be able to become alive.


Huh? That code should -in theory- create NEW cells (therefore, in place of DEAD cells), if the neighborhood of a DEAD cell contains exactly 3 ALIVE cell. However, this code DOES NOT ensure that an ALIVE cell in the same conditions (excluding itself from the count) will survive. In fact, your code only contains conditions for creating new cells, and for killing cells due to overpopulation/loneliness. There's no "survive a generation" code.

I suppose you're using a still life or an oscillating pattern as a test? In particular, a pattern of 4 cells:

   1 1
   1 1

should survive indefinitively. Each cell has exactly 3 neighbors, so it survives, and no new cells are actually created. That's a still life.

Share this post


Link to post
Maes said:

I'm not sure that passing a struct with the address modifier (&) will work as intended: what the function "equality" sees might not be what you meant at all. I would expect it to be like this:

bool equality(tiles* a, const tiles* b)
and then referencing the various members with
a->red=... ;
a->green=...;
etc.

Also, how do you use/call it?


Well, it works perfectly. I found it after 30 secs of Google-ing.

But now I tried your version too, and it also works! But at the first time, it didn't!

Maybe I forgot those arrows. Thanks anyway!

Maes said:

Huh? That code should -in theory- create NEW cells (therefore, in place of DEAD cells), if the neighborhood of a DEAD cell contains exactly 3 ALIVE cell. However, this code DOES NOT ensure that an ALIVE cell in the same conditions (excluding itself from the count) will survive. In fact, your code only contains conditions for creating new cells, and for killing cells due to overpopulation/loneliness. There's no "survive a generation" code.

I suppose you're using a still life or an oscillating pattern as a test? In particular, a pattern of 4 cells:

   1 1
   1 1

should survive indefinitively. Each cell has exactly 3 neighbors, so it survives, and no new cells are actually created. That's a still life.


Someone told me that I forgot the equality (<=i+1 instead of <i+1) in the counting loop, that was the main mistake. Also, I added a " arrb[i][j] = arra[i][j];" line so now, if something is wrong, cells are staying in their place, not disappearing.

My next problem is that I added two types of automaton functions, but only one of them starts to work, even though the round loop includes both of them.

You could see the automaton already, now I show the round loop.

	while(!end)
	{
		al_wait_for_event_timed(event_queue,&asd,0.001); //várakozás


		 //ha enterre aktiválást akarsz, ezt a két ha függvényt tedd be!

		if(asd.type == ALLEGRO_EVENT_KEY_DOWN)
		{
			if(asd.keyboard.keycode == ALLEGRO_KEY_ENTER)
			{
			Test(fielda,fieldb);
			Conway(fielda,fieldb);
			end = false;
			round++;
			for (j = 0; j < fldheight; j++)
				{
					for (i = 0; i < fldwidth; i++)
					{
						fielda[i][j] = fieldb[i][j];
					}
				}
			}
	}


		for (j = 0; j < fldheight; j++)
		{
			for (i = 0; i < fldwidth; i++)
			{
				al_draw_filled_rectangle(20 + (4*i), 20 + (4*j), 24 + (4*i), 24 + (4*j), al_map_rgb(fielda[i][j].red, fielda[i][j].green, fielda[i][j].blue));
			}
		}

[*a lot of Allegro commands to write texts onto the screen, not important now*]

	}
What is wrong?

Share this post


Link to post

At this point your code is too long to keep posting segments out of context, so your best bet is to make a public repository where at least people can browse the entirety of your code. I have no idea what Test() and Conway() do, for instance, so how could I tell why one works and not the other?

Share this post


Link to post

Oh, sorry, I thought I show it already. Here it is!

Don't run it with Code:Blocks or anything, this is just the main file from the MSVC project I'm making it in.

Share this post


Link to post

Also, it's time to be more specific about what the problems are.

Saying that a function "starts to work" (or fails to do so) doesn't sound very clear. Does it start working or not? Do all loops work? Do you get runtime errors or not? Do all variables change as they should?

It's also about time you start using a debugger, tracing and variable monitoring, and pinpoint errors down to specific lines or variables. Otherwise it's pointless using MSVC: you could just as well use notepad and a command-line compiler, and go through a painstaking formal proof of the entire code each time you encounter a problem. This you can only do for really short programs (or if you programmed in the 50s), there's no point in doing it the hard way today, not since you already "paid" for the overhead of using fancy IDEs with debuggers....

Share this post


Link to post

1.)

I didn't get any kind of errors at the moment, I can build the solution without any problem. The "bad thing" I can notice is that red cells doesn't move. The function is ready, I even call that in the loop, but probably the function that comes then clears everything it does.

Sorry, I can't explain it better.

2.)

Ehm, the only part I could get from that first sentence is that "It's also about time you start".

Anyway, the reason I use MSVC is that:

a) I simply couldn't add Allegro to Code:Blocks, installing that stuff was a pain in the ass for me.

b) When I started this file, I wanted to use regular Windows Form Application for this program - to make a useful GUI as soon as possible. But later I stayed with Allegro windows and elements, I didn't expect for it when the whole thing was started.

So you think that I should go back to Code:Blocks?

Share this post


Link to post
Katamori said:

I didn't get any kind of errors at the moment, I can build the solution without any problem.


Getting an error-free compile is of course essential to get things to run, but it doesn't mean that the result will be correct. Far from it.

Katamori said:

Ehm, the only part I could get from that first sentence is that "It's also about time you start".


Work on that first, then :-p

Google translate, if you have, but REALLY, you have gone beyond the limit where someone else glimpsing at a short snippet of your code can reveal a problem. You'll HAVE to upgrade your debugging skills yourself. Litter your code with printf and cout statements, if you have to, but don't expect anyone to run your entire program in their heads and telling you "there's the problem". It's way past the point where this is possible.

Katamori said:

When I started this file, I wanted to use regular Windows Form Application for this program - to make a useful GUI as soon as possible. But later I stayed with Allegro windows and elements, I didn't expect for it when the whole thing was started.


It's premature to fiddle with libraries and GUIs when you still have to get the basics of algorithms and good C/C++ coding practices down. That's just my opinion, though. Certainly it doesn't help you at this time.

Katamori said:

So you think that I should go back to Code:Blocks?


No, but you really need to start debugging things yourself before posting here about every other problem. An average hobbyist/learner project may get hundreds of build/recompilations/test runs before they get most things right. If you e.g. tried yourself for about 1 hour or two and exhibited some major progress before posting here again, it would be different.

Share this post


Link to post
Maes said:

Getting an error-free compile is of course essential to get things to run, but it doesn't mean that the result will be correct. Far from it.


I know, that's why I told that there's no error messages. You asked me for it =)

Maes said:

You'll HAVE to upgrade your debugging skills yourself. Litter your code with printf and cout statements, if you have to, but don't expect anyone to run your entire program in their heads and telling you "there's the problem". It's way past the point where this is possible.

[...]

No, but you really need to start debugging things yourself before posting here about every other problem. An average hobbyist/learner project may get hundreds of build/recompilations/test runs before they get most things right. If you e.g. tried yourself for about 1 hour or two and exhibited some major progress before posting here again, it would be different.


Obviously, I know that I have to find the mistakes by myself. I do it too. All the problems I've posted here was about 30% of all the problems. I could solve the rest, but there are some of them that I can't solve even with Google-ing. For example, I've never seen before that a function clears tha changes that another did (this is the current "bug"), in this case I don't even know how to start it.

Maybe I'm a rookie (I mean, I SURELY am), but I wouldn't wait for help if it wouldn't seem to be hopeless.

Maes said:

It's premature to fiddle with libraries and GUIs when you still have to get the basics of algorithms and good C/C++ coding practices down. That's just my opinion, though. Certainly it doesn't help you at this time.


I totally agree. The funny is that there's a course at the university where we started using Visual C# on the same way (with form applications) without any knowledge about C# so some of the classes were kinda chaotic :D but of course, handling windows were a bit easier.

Sadly, this is not the same with C++.

Share this post


Link to post

Your grid (field) appears to be a 2d grid of red/green/blue triplets? Any reason for that extra data, given that cellular automata logic normally only needs on/off?
I'd just make a grid of 0s. Sprinkle it with random 1s. This will be the input grid. Have the output grid initialized as same size, all 0s.
Loop through each cell in input grid (for y in height, for x in width, in the 2d input grid). Count number of its 8 neighbors that are 1. If such and such conditions, make the output grid at the same location 1 or 0. The edges are the annoying cases because its neighbors are on the opposite side of the grid, assuming you want the grid universe to warp back on itself. But the same modulus condition can be used for every cell if you use modulus.
Then input grid = output grid, do all again.
Before allegro, maybe just use a small grid like 30x20 or something, and print 0/1 characters instead of graphics. Just to make sure the logic is even working right.
If you observe odd behavior that isn't doing what you want, print culprit variables every iteration to gain insight as to what's going wrong.

Share this post


Link to post

Oky, well... that's what I have at the moment:



Notcie the bug around the half, when pixels were but on a bad place. Don't worry, it's gonna be fixed!

Thanks for the patient and precise help for Maes and gggmork and actually everyone who has posted here until now.

The project won't stop but there's no doubt that this is far the biggest work I've ever done with any kind of programs.

Feel free to feedback! - ...but there won't be any public versions for a while, because it still needs a lot of polishing.

Share this post


Link to post

Cursor is fixed, classed are used - that's all yet!



But Build 5 will be released for everyone!

Share this post


Link to post

Does the red vs green have identical behavior? Like a "walker" made of some red and some green will behave as a normal walker? I just started learning plain c yesterday with code::blocks.
I would probably make "tiles" map to keys, like press a key and whatever pattern you draw as the tile will instantly draw, a different key makes a different pattern etc. Or some effect like click on a spot to make a big spiral appear of whatever thickness/etc, just to see how it behaves. I made game of life for python once where you can choose any possible cellular automata rule, not just the specific ones for the game of life. Few had interesting behavior though if I remember.

Here's another cool thing that is fun to play with and another problem to practice on. Take a bunch of frames of an animation, like a guy walking or whatever, like 100 frames or whatever. Now "splice" the frames over time, like make the first frame where each next row is from the next original frame. It makes "time" "bend" downward across the animation, like he'll walk slanted ahead of his feet, and it looks cool depending on motion, like things that turn or rotate are interesting. And then you can use the "bent" animation as the source for a new re-bent animation, feeding the output back to the input. Which is kinda related to the concept of positive feedback I think.

Share this post


Link to post

Different colour cells don't react with themselves. The only way they can is that replacing. For example, if a cell has 3 Conway cells in neighbour, a Conway cell is born there, either if there's a red cell already or not.

Conway cells are green, test cells are red. Their rules are different, consequently they born and die on different ways.

Patterns are gonna be added, but on a special way: they will be created by special generators that you can place on the map and those generator will create a new pattern in every 5 (or more/less) rounds.

I'm gonna add more kind of automatons (like Langton's Ant), but now, I'm thinking on that how can I make the strategy part of the game more custom and unusual.

Share this post


Link to post

Greetings,

I haven't updated this thread for a very long time! Fortunately, I'm not hunting for programming help here anymore - instead, I found a better place for it. =)

After a long break, I completely remade the engine, keeping the most basic things only, like visualization, and the color selecting menu.

This version is dedicated to an entirely new project I've previously wanted to do, and even was mentioned in this thread if I remember well.

This plan is to create a logic-based game, with an integrated editor. My plan is to be able to create, save and load maps and states - to give the ability for everyone to make their own maps. But this is kinda far yet, so now I'm working on the gameplay elements. Basics are ready!



I don't upload the source code until anyone would be interested in it. In that case, I can provide you with a download link! =)

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×