Files

640 lines
39 KiB
Plaintext
Raw Permalink Normal View History

Episode: 361
Title: HPR0361: Programming 101 Part 4
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr0361/hpr0361.mp3
Transcribed: 2025-10-07 18:55:36
---
.
Welcome to Hacker Public Radio, my name is Soak, programming 101 Part 4, the Game of Life.
First up, more feedback. As it fluxes, sent me an email, I will skip some of it like the praise.
I did like his line about I do not have the time of a testicular fortitude required to spread the good word though.
He mentions I skipped saying the brackets and the print statements.
Thinking back, I probably did, although I believe I got the sample code right each time,
because I checked, I ran all of them correctly to make sure I was saying the right thing.
I probably just said print x meaning print open brackets quotes x quotes close brackets,
but skipped some of it because print x is easier, so I apologise if that confused anyone.
He also says that my terminology is a bit confusing, I call brackets as brackets,
whilst technically this is correct, there are square brackets and greater and less sounds and so on.
So we've got shift 9 and shift 0 for brackets, and then we have the two keys to the right of the P
for the open the square brackets and close square brackets.
We've also got the open curly brackets, close curly brackets there,
and the greater than less sound on the comma and the dot full stopper period if in America.
He does mention a bit more about why this would be a problem,
but I would not confuse you with discussions about lists and two pulls and so forth.
To clarify, I do call shift 9 and shift 0 brackets, not parenthesis,
as I have mentioned in the previous episode.
The one's to the right of P, the one's that look like you've taken a square splitter down the middle,
I would call left and right square brackets or open a close square brackets to distinguish them,
and the comma and dot less than and greater than sound,
I would call less than and greater than, even the very opposite brackets.
And if we do need the shift and then the one's to the right of the P,
I would call them curly brackets.
This lock may get a bit confusing, so if you want to go head over to zoke.org
and zoke.org forward slash Python, I have a list of all the show notes in my scripts
and the code and sample code and everything there, so go and have a look at that
and see if that makes any more sense.
And you can see how much I had like bits like this because then on the script.
Anyway, this could just be that something I was used to at work
because we were in Microsoft and Visual Basic Shop where the brackets were most commonly used,
you know, shift 9 and shift 0.
It wasn't C, so you didn't have curly brackets or anything like that.
So that's what we all used, and I apologize if it confuses anyone here.
Please refer to the example code I give us that should make it look clearer.
Tolly meld me and said he'd written a game of life program
and he did attach it but I haven't read it yet, not because I don't want to.
But the same reason I'm not listening to the yelkie mantis is episodes.
I don't want to mess up what I'm doing.
I want to write my game of life and do my Python process, podcasts,
without stealing all the ideas either intentionally or unintentionally from other people.
So Todd, I will be checking this code out after I've finished the game of life.
So when I've finished this episode and uploaded it basically,
one other thing whilst I remember,
a few people have said I speak too quickly.
I have noticed as a whole the English do speak faster than Americans
and with all the different accents in the UK,
it can cause issues, especially if you are a non-English as a first language listener.
So I'm intentionally trying to slow down.
I do try and slow down anyway.
I have done this since I came to America.
It's not a problem around Mrs. Soak or Mini-Zoak anymore because they know me.
It's not a problem around her family.
There are a few things like her sister will never really want to speak to me on the phone
because she can't understand me in person.
It's fine, but on the phone there's something that it causes issues there.
I do notice sometimes I'll get excited.
No one gets any of that.
So I'm intentionally trying to slow this down even more than normal.
So hopefully it makes a lot of sense because programming is confusing.
Well, it's not that confusing, but it can be when you're trying to learn new processes.
So I will try and slow this down.
Again, as I said, Zotorg, I have the scripts that I write.
So you can also look at that.
And of course, the Hacker Public Radio website will have the sample code so you can go and look there.
And hopefully it will make sense.
But if you have any questions, let me know at the end of the episode I give my feedback details.
So just email me, let me know.
Now, on with Python.
So, the game of life.
Some of you will know that the rules already I'm sure, but for anyone who doesn't, they are.
For a populated square with two or three neighbors, the plant lives.
If there's not two or three neighbors, it dies from overcrowding or loneliness or whatever you want to call it.
For an unpopulated square with exactly three neighbors, a plant appears through pollination or whatever.
That's it.
You have a grid of whatever size you can make any size grid and the new seed plants in there.
And then let it grow.
It's fast and simple.
So let's just think about this to begin with.
It is always better to think about the code to begin with rather than rushing headlong in and making harder code.
If it's simple enough, you can do it and if you're a good enough programmer.
Most of the time you need to think about this and figure it out.
So let's assume we're going to make a 10 by 10 grid, 100 squares in total.
Actually, we may want to change this later to be 80 by 25 to be the full console width and height.
But as long as we do this right that way, matter.
We can just create a variable and then change the variable, no big deal.
So we'll have the current field, which is what we're showing on the screen at the moment.
We will need to run through this field to figure out what lives and what dies.
But we will need to make a next year's field to show that.
So we don't overwrite the current field and mess it up before we finish calculating what lives and dies.
Then we need to copy the future field over to the current field and then we're ready to loop round again.
So let's start by writing some pseudo code.
I words that aren't really code but have the same loops and so on to make our life easier to code.
Some of this will be a very high level, but we can expand this later.
So we want sort of load the field in, run the simulation, circling around the new fields.
Okay, seemingly high level.
But if you're not sure, write it high level and then expand later on.
So let's expand the run simulation part.
This is how you write something complicated.
If you look at something and think, wow, how do I do that?
Just split it down into smaller, smaller parts until you know what to do with.
So let's continue.
So run through the current field.
For each square, we need to count the neighbors and put the next year's crop into the future field.
Copy the future field over to the current field.
Still not hugely helpful, but we can start putting in some code like words in there.
For each row x.
For each row y.
Count up the neighbors.
If current xy is alive.
If neighbors are two or three features alive.
Else future is dead.
Else, if current xy is dead.
If the neighbors are three.
Future is alive. Else future is dead.
Then next x and next y.
Fairly simple, but that's looking a bit more like code.
We should see how the code will begin to float.
We can expand bits of it like the count up the neighbors section.
That will become something like for current x minus 1 to plus 1.
For current y minus 1 to plus 1.
If xy is alive, neighbors count plus 1.
And then looping round.
So that would loop round all the neighbors.
But it would also count the current neighbors, so we would need to tweak that.
Also, there is another problem that you may not have thought about.
Have a little thing and see if you can figure it out.
Why can't we count from x is minus 1 to plus 1 to get the 9 by 9 grid?
Just talk about this yourself, I'll just get a drink a moment.
Right.
The reason is that may not always be a 9 by 9 grid round the square.
If from the edge it won't be.
If we are in the top left, for example, the very top left corner,
we will only have three neighbors.
The one to the right, the one down, and the one diagonally down to the right.
The others are going to be off the edge of the field.
Up, so gone, left, so gone.
There are a few ways we can get around this.
We could add a bunch more code to check if we were on the edge
and then check around the various places.
However, I think that given almost all machines nowadays have a ton of memory.
At least a gig.
We will expand the field to be two wider and two longer.
One extra one all the way around the edge.
This makes us be able to avoid the extra code checks.
It would use more memory.
I'm going to do this way to demonstrate this.
So for a 10 by 10 grid, this would actually be quite a big overhead of memory.
100 squares 10 by 10 would become 144 12 by 12.
However, for an 80 by 25 standard terminal dimensions,
this would be 2,000 compared to 2,214.
And would be less and less the more squares you add.
Of course, if you wanted to run this on a website with hundreds of hits,
you may want to take his speed compared to the memory
if you're actually joining it all on the server.
So something to be aware of, but don't loosely pay for it.
Try to think of these problems though before you start coding.
But any code that works no matter how slow is better than no program.
Just remember a program that works fast is better than both of those.
Now, now that a lot of the pseudocode is done,
although yes, most of that was just a demonstrator.
I have written the game of life program before and I'm aware
so the best ways or better ways of doing it.
And I tend not to overcomplicate pseudocode
because I have got self years worth of experience as a developer.
So I don't have to drill down as much.
If you want to continue and drill down to do your own one, please go ahead.
But I mainly use it just to figure out any habits of the code.
Just make me think in the whole idea of how the code's working.
But now we can start writing the actual program.
To make it easier later, if we want to change the dimensions,
we should make a variable with the height and width of the field.
That way, to change it later, we simply go into the variables
which we should put at the beginning of the code and make the changes.
First up, we actually want to make this a run-able file.
So we need to create a new file, we'll call it gameoflife.py
and we'll give it executable permissions.
To do this on Linux, in a terminal in your code directory
or wherever you want to put the gameoflife.py,
type in touchspacegameoflife.py.
The touch command, if you don't know, does two things.
If the file doesn't exist, it creates a file
and it will make the creation timestamp of the file now if the file does exist.
Then run CH mod space U plus X, no spaces there,
space gameoflife.py.
The CH command, short for change mode, can change permissions.
Now you can use the numbering system, so making a file 775, for example,
but I really try not to do that because it does override all of the permissions.
If you get it wrong, you've just screwed up the file permissions
and I did that on my home directory once, and it wasn't fun.
I made permissions 6.00 or something,
and I forgot to say don't do directories, so I took off executables,
status for all the directories, and you couldn't move into any of them.
I did a quick search on the net and found some code to actually fix that
if you do an if file type dash D or something,
there's a say if it's a directory, and that fixed it.
But that's why I'm really not a fan of using the numbering systems.
I do prefer to do the U plus X, which is user executable permissions.
I find it easier that way.
This way you're simply adding in executable for users.
Briefly, as this is in the bash scripting episode,
the U says things to the user permissions,
the plus says to add, and the X is executable.
The file name then follows.
To remove, you would use U minus X.
If I recall correctly, the options are U for user, G for group,
O for other, and then plus for add minus for subtract,
and R3 is W for write the X for executable.
You can mount the CH mod to command for more information if you require.
Now, if you're running Windows, I believe you should already have the execute permissions.
So you just need to create the file.
There are Windows versions of touch, but it may be easiest just to open
a notepad or similar, and for single space, so you can save the file and save it.
I don't have Windows handy with Python installed, so this may not be true.
I did actually download a Windows RC7 RC.
Whatever, that was the new one that you can get for free for the next year.
And I may have a play around with that, but at the moment, I haven't tried, so I don't know.
I imagine everyone listening to this can either figure it out themselves,
or don't need to because they're running Linux.
Also, I don't know if you can actually simply run the program
or you need to call Python first.
If this really is an issue for someone, let me know, and I will investigate.
Now, we've created a file.
We need to tell the computer how to run it.
We have to do the Shabang and point it towards Python 3.
This is really simple. We just put hash pound octopop,
exclamation mark forward slash usr forward slash bin forward slash ENV space Python 3.
This does work fine for me, although depending on your version of Linux,
it may be Python 3. Hell similar.
Basically, we point it towards where Python is stored.
On a bunch of it knows where Python 3 is, so we can just put that in.
You may need to put slash usr slash bin slash Python 3.0 or something.
Your mileage may vary, as they say.
Now, I do need to explain about a new type of, or rather an extension, of variable.
So far, we've only had single variables, one number, one string, and so on.
Think of this like a single box, where we can store one thing in.
Now, we could set up the field of 100 different boxes,
but how do we easily organize 100 boxes placed around randomly?
How would you explain to someone how to find a specific box easily?
So instead of having 100 different boxes, we're going to use what's known as an array,
which is many boxes stuck together.
Think of this like a row of cubby holes.
You can explain to someone that there are cubbies on the back wall and they can see them,
and you can then say what you need is in the fourth cubby hole from the left,
and we'll know exactly which one that is.
This would be better than having the 100 boxes scattered around on the floor randomly.
Arrays are basically like cubby holes.
You can have a one-dimensional array, although that would just be a normal variable, a single cubby hole.
A two-dimensional array would be a row of cubbies that are only one cubby high.
A three-dimensional array is a row of cubbies several high and several long.
You can continue this into as many dimensions as you wish,
although if you want to know what they look like, you may have to ask Klaatu
to explain the finer points of multi-dimensional space.
Okay, just kidding about the Klaatu bit.
It's a running joke about him being an alien from out space,
and I'll spread up my speech, I'll slow it down again.
We should set up a two-dimensional array 10-wide and 10-deep,
and that would be our field.
In Python, however, you can't do arrays as such.
I mean, you can make a list where, which is a one-dimensional array only,
you can extend this using modules,
but I don't want to talk about these extras yet,
just sort of the basic fin in a Python,
because I haven't even gone over lists yet.
So we will have to be slightly creative here.
We will make a list of length width times height,
and convert any xy coordinates onto that list.
Slide pause here whilst I write the program,
and then I will go through and explain it.
I will also try to put a huge number of comments into explain it.
Anything slightly clever or not immediately obvious I tend to write a comment for.
Just in case the next person who comes in and lets your code looks
and doesn't spot the clever bit,
and breaks your code, for example, the SSH vulnerability,
when they didn't clear the memory out
to include randomness in the memory.
I have not looked at the code,
but I feel if there was a very big comment saying,
warning, we do not blank the memory here to increase the entropy on it,
do not change this.
Or something similar, the problem would not have occurred.
The person changing would have read through it.
Oh look, it says this, and then investigated into it.
Just remember, if you don't amend the code within a few weeks,
you do actually forget everything about it.
This is just one of these weird things.
You write a program you move on to another program,
you forget the first program you wrote,
and you come back.
And most long term developers have actually done this.
You look at OK and say,
it's the more on thinking what they're doing,
how will they try, oh wait, I did that.
Oh shit.
So, we've all done that.
It's quite a humbling thing when you realize
you have no memory of writing the code.
But it's one of these things.
The writing the code gets stuck in short term memory
or something, and you forget it because it's just writing code.
It's not actually something, the code itself,
how you did it, you don't need to remember.
It's how you write the code, not what you wrote.
So, you should write the copious notes.
So, for example, when I write the code,
I will loop around a three-by-three grid to cow-click neighbors.
Because the easiest way to do this is to loop,
looping from minus one to plus one,
to pick up all the nine squares in the three-by-three grid.
This count will be off by one,
if the middle spot has a plant in it.
Because I will write and note in the comments to point out
that I'm aware the count's going to be off,
but I will fix it.
And then when I correct for this,
I will comment why I'm doing this and say,
you know, as per earlier comment,
over count.
That way it should be helpful if someone comes in
and wonders if I realized it could over count.
In fact, one of my lecturers always said
you should have more comments than actual code to explain at all.
Now, sometimes code's obvious enough.
It's only a small comment is required,
but if you don't, put more comments in.
All right.
While I think that slight pause was actually about two months,
which is quite a big slight pause,
mainly because I kept rewriting bits of it
as I didn't like it.
And I'm still none in love with all this code.
But it does work.
And I think it's at least fairly good.
I haven't made a few interesting choices,
not necessarily because it's the best way,
but because it demonstrates specific things,
because I am trying to teach you things here as well.
So without further ado,
here is the code and the explanation.
Go look at the code whilst I'm going through this,
as I'm not going to read all the code out in full.
In fact, I'm just going to say this bit does this
and around this line.
So go to the Hackfile radio website,
you should find it there.
In the show notes, go to zoke.org,
forward slash python, forward slash four.
I think this is going to be the fourth app.
I will have my script there as well as the code.
And I'll link to the Edgepile episode itself
so go and have a look at that.
Look, one of them and go through it with me now.
Okay.
Pound exclamation mark, forward slash user bin,
end of python 3.
As I said, I'm going to skip a lot of these.
I'm not going to say forward slash user, forward slash bin,
forward slash end.
I'm just going to say enough to see
which line I'm talking about.
So, user bin end of python 3.
That has to be at the top.
This lets the computer know how to run the program.
I then also have a huge amount of explanation at the beginning.
I use hashes which are comments within python,
as I've already explained,
to put bits at the top, the license, and so on, so forth.
I put this code out under the GPL,
although I'm not intending on creating a source forage project for it or anything.
If someone else wants to do great, go ahead.
I would like you to say that I brought the original,
but that's just pure politeness.
I would also love it if you did updates to it,
made it all fancy and shiny and websiteed to 2.0,
and I'm really probably going to not do a huge amount of updates.
I'm going to do some updates to it over the next few months
to demonstrate some more things,
but I'm not going to do a huge amount of updates.
I'm just going to put this out just as a complete demonstration,
and as it's one of the first,
sort of the first big python program I've written,
I'm going to GPL it just because that'll make 3.30 happy.
And maybe he won't that be off next time on Cranks.
The gate.
After the license, I list all modules.
Now I split these up into sections by the houses again,
just to make it easier to read so you can see what's going on.
When you're skimming through the code,
you can see that's modules.
This is the license.
This is variables, so on, so forth.
So first up, modules.
By default, python doesn't actually include a whole ton of things.
There are a bunch of modules, however, which extend Python.
In this case, I add in random OS and time.
The random module allows you to use random numbers.
The OS module allows several things,
but in this case, we're going to use it to clear the screen.
The time module allows us to use the sleep command
to wait in between cycles so you can see it.
So it doesn't just go blah, blah, blah, blah.
And that's done.
It was a bam, bam, bam.
Next, I set up variables.
Now, some of these I'm actually using as what's known as constants,
i.e. I will not be changing them.
But putting them here at the top means if you want to change any of them later,
you know where they are.
I should point out I'm trying to kind of use Hungarian notation.
However, I couldn't actually find a formal list of Hungarian names in Python.
So I'm kind of making them up here based on some of the things we did where I used to work.
So someone doesn't know if a formal list I'd love to know.
So things like i's ninja, s is a string,
l at the beginning is a list, so l i's a list of integers.
Then you have the, that's the lower case, you have the underscore,
and then you have the actual thing in camel case.
So it makes sense to me that's what I'm used to.
But again, if someone's got a formal list,
this is a good way of doing it in Python.
I'd love to know.
I set up the width and height here.
So if you want to amend it, you can simply do it here,
and you save and rerun the program.
You don't need to be digging through the code all the way.
I also have the iterations and delay between them.
And as I commented, this will greatly increase the time taken to run.
If you put them up too much, so really be careful.
Next up is the fertility,
which is how the program randomly feels filled.
Changing these allows you to change how many plants are made.
Too many and they will all die out from overcrowding.
Too few will make them all die out from loneliness.
I have it at about third.
A fraction under a third of the field is full.
It seems to work quite well.
Then we have the fields themselves.
They don't really actually need to be here.
The rest of them is actually sort of more set up files.
But they were the only other big variables I use,
except for a couple used only in a few lines.
So I put them in there.
Next to the functions.
Functions are bits of code that can be called from anywhere within the program.
Well, kind of will in C and visual-based things,
you can get a bit more complicated when you have four or five different files
to make a single program.
But for all intents and purposes in Python,
you have one file.
And so you can call it from anywhere.
I could have put these in the main part of the code and not actually have it as a function.
But it's easier to keep the full amount of code for one section to be fairly small,
making it easier to read.
Functions are defined by using a death command for define, of course.
And then a name with brackets or parentheses.
I still hate saying that word.
You can pass information in to a function if you want by putting in local names inside the function.
I am not here, which isn't actually necessarily the best way of doing it.
But it does work.
I had some issues trying to pass them in and broke it and had the wrong version.
And there's a couple of bugs in my program and I removed it and got it working.
So I never got around to putting them back in.
Some programming languages do allow you to pass variables in by what they call reference.
And not actually allow it to change.
So you can pass a value in and it would always be the same value returned.
Other programming languages don't allow this.
I do need to read up and see if Python can actually do this.
But I don't believe it can.
I will check and confirm though.
Functions do also allow you to return functions to the bit of the code that call it.
But using the return command, this can be useful if you want to tidy up some text to say to export it.
And you want to print it out and have the same thing at the beginning of the end or.
You want to create a function for example that you can call add space on end or similar.
And you call it passing the text into it and the function would add space out onto the end and return the newly formatted string.
Or even print it out directly.
You could also use the return save for function worked right or error.
For example, a function called load config file could return an error if the config file was not found.
Then you can check the return and handle it appropriately.
So something like for example, death F and score load underscore config and score file.
Open brackets S underscore file name close brackets.
Some code to load filing if file found whatever the requirements were.
So if file found return to else return false.
That way when you call the function which I've started with an F share to function.
You can do something like if F underscore load config file equals equals false colon some warning there.
You could print a warning stating no file found creating one or using defaults or depending on how you can use the config.
Now back to my game of life program.
The first function makes the fields up.
I use a function here not because it really needs to but because it reduces the amount of code in the main section.
If you've made pseudocode beforehand and you have you can have functions that refer to the pseudocode and it makes it look nicer when reading through it makes it more readable.
And again with all about making it more readable.
Think about it this way.
If you're reading a book they tend to split up into chapters, paragraphs, sentences they don't have one big chunk of everything in one or long line.
That's what we're trying to do here. Break it out make it easier to read.
As I mentioned before I am a big proponent for making it easier to read.
I would actually write code that is actually slightly slower if it makes it easier to read much much easier to read.
Mainly because computer so fast nowadays an extra of millions of a second makes no difference at all.
The user is going to be sitting there if it takes in 2 seconds to print or 2.001 seconds or even 3 seconds it's really not going to notice it will be noticeable.
When you're coming into change it next time making it easier to read will be very noticeable.
Anyway I do have a huge comment bit here to explain how the function works, what the inputs and outputs are and so on and so forth.
Again this just makes it easier for the next person editing the code.
This was something we did.
Raised work you had sections of what's going on even little version in 12 bits and it just mentioned what changes have been done.
This is a fairly short function it just loops around and depends on extra 0 on to the end of the fields that we made earlier.
This is so you can easily change the height and width of the field.
Now the function does create 1 extra 0 at the end which is a small waste of resources.
I did put a comment in here explaining this but by now this code should make sense for everyone with the possible exception of the dot append command.
l i and score current field. l i says it's a list of integers.
Current field says it's the current field and dot append and bracket 0 brackets adds another cubby onto the end containing a 0.
Yes x and y are not Hungarian but they are simple counters.
If you've ever done maths x, y and z are the three coordinates x is width y is height and z is depth.
Yes maths, height and z and not height as people seem to say which I don't understand because there's no h at the end so it can't be height.
But anyway the field is to the mention of course so I'm using just x and y here.
Now the final command would print out the length of the current field but I commented it out.
I was using it to debug a problem I was having I had the x and y around the wrong way which is silly but there we go yes I screwed up and made the mistake.
It happens get over it I fixed it it works now that's the main thing don't worry about if you make a mistake put lots of extra debug commands as I would call them in.
I commented this out here although I could simply delete it now but I left in just to demonstrate the command len returns the length of whatever you pass it.
You could think of this as a function where you pass in the variable and it returns an integer of the length in fact this is an internal function of Python.
The next function is to see the field.
As the command says it doesn't actually clear the fields out so do not see a field that has plants in it already or it will overpopulate.
It shouldn't be a problem but I did put this in to remind me in case I need to change it later.
Next up I put a comment starting to do which is to do in one word and capitals.
I do that in one word in the capitals make it obvious when you look through it and use it to search for later when you need to update.
As I say here it would be nice to allow the user to add where the plants are.
There are a few interesting things that fire gliders back and forth and lots of things I have to explain later about the game of life.
So I said you know it would be nice to allow people to make their own ones up.
I also point out why we sit X and Y to be 1 and not 0.
Again this is to make sure I don't break it later and come back and think oh shit it starts at 0 and not 1 I should make 0 and then it will break.
Because we're not checking for the edges.
Now again it should be fairly simple.
Once again I have debug line commented out as I again had a problem earlier when I was making up the fields.
I made a row the correct width and added it to the number of times the height balls.
The problem with this though adding the same row in makes actually the same row go in several times.
Not just new variables of the same amount but the very same variable.
So when you see you end up with almost all plants and they instantly die out because each row was the same as the others.
So you go through the first one and you know no plant plant plant plant plant or whatever and then by the end a 30% chance doing 10 times chance that every single one is going to have a plant in once.
This is the not clearing out the field thing as mentioned earlier.
So I printed out what the field was either like to show me and then I realized all the rows were identical no matter how many times I ran it and obviously that wasn't right.
So I looked that and found that out again printing stuff out is your best friend.
If a program is crashing somewhere and it doesn't tell you anything not even where which line it was running on it just you run it crashes.
Print one two three four throughout the code run the code see what number prints out on screen when it crashes.
Oh it's after three so you look at three and before four and then you add three point one three point two three point three or whatever.
And as many as you need even after every single line if necessary and then you will find out this line is crashing it.
Then what you can do is take part of that line if you are doing a dividing one variable by another you print one variable out then you print the other variable.
Oh that variables zero and that's why it's erroring because I'm dividing by zero for example printing stuff out on the screen is the best way of debugging really is.
Absolutely brilliant even stuff like visual basic or visual studio it's got this huge visual thing and you can step through one line at a time one line at a time.
You can get errors and it can bounce you to another bit of code where your error handling is.
You can do some sneaky stuff to return but it's not great basically.
So printing stuff out is always very useful.
Okay another big comment here explaining how I convert the list into XY coordinates again to explain it to me later to remind me.
Hopefully this is self-explanatory which is the way it should be with comments.
Then we have a function to print field out first up it calls the OS dot system command with clear to clear the screen.
I have no idea if this is going to work under windows and I didn't actually put a comment on there saying that so bad so don't do it again.
Then I print the current year out.
I did this because it actually proves something is happening.
I did have a bug in my program when in an earlier version where I was creating the next field and it didn't copy it back over correctly onto the current field.
So the same field is printing over and over again and it sat there and didn't look like it was doing anything because it didn't change the screen.
So I had to be year improved it was looping but it wasn't updating the fields again printing stuff out the screen helps you fix the bugs.
Now we loop around each column and then each row to run through here.
Now I convert the ones and zeros we have in the list to be this weird plant looking symbol.
It looks pretty them with all the ones and zeros on the screen.
The first version I did had just ones and zeros and it was stuff on screen all everywhere.
So I convert the ones and zeros to space or the plant depending on the ones that become the plant.
The zeros become the space of course.
This time I did put a comment about different OSs.
I have only tried a Ubuntu but it is ASCII which if I remember correctly it stands for American Standard Code for information interchange.
At least I think that's what it stands for.
So we should work on all OSs as I comment there.
We loop through each row and figure out what to print for the entire row before printing that full row out.
You see if you just print each one out on its own it would print a single plot per line, single one out.
So you would have 100 lines and it would just look terrible so we do a row at a time.
Then we use the time.sleep, the time module I mentioned earlier.
To delay for however long we started at the top.
This is the only time we actually set it here so I could just put it in.
However it is much easier to have it at the top so you know where to change it without searching through the entire code.
This makes it a lot easier in bigger programs.
Now the final function is grow field which grows the field according to the rules.
This function does actually have more comments than code because it's a little more confusing.
I loop around 3x3 square around each plot as I said earlier.
It ever counts if there is a plant in the middle.
Look at the code, read the comments and see what you think.
This bit of code I actually I think my best code in the whole program.
We could remove the ever count we make but it's easier to ignore as I do here.
It saves down on a bit of calculation.
Not necessarily saying it's absolutely fantastic code I'm just saying.
I think my best code that I've done.
Now as I comment I had a problem here and I'll explain why I think it didn't work.
So I did the code in a different way.
Hopefully that entire function makes sense.
The last bit is the main segment.
And the entire code without comments is simply make field, seed field, year one,
whilst year is less than iterations plus one, grow field, print field, year is year plus one.
That's it.
It really does actually look a bit like pseudo code that you may have written which is how it should be.
Well that is the basic game of life.
Now I need to read up on how to do some more graphical things to try and make a nice graphical front end.
We can simply change the print field function to do this.
So I will try and do that a lot faster than this one.
Hopefully a few more weeks we can get something else sorted and I can start recording it again.
I will see what other updates I feel like doing for the program also.
And then we can start doing some simple version number on the code.
Also if there is something specific you would like to see changed in this program, let me know and I'll see what I can do.
This also sort of marks the end of the Python lessons in a way because I have actually gone through some of the most important parts of it.
Don't worry I will continue this series for a while.
However I will do a focus on writing specific programs to do specific tasks and through that introducing a maybe a few more new things.
But not actually just talking about this, how to do this, how to do that, just saying here's a program to do this and let's go through the code.
That way you should be able to see how I would write programs myself which isn't necessarily the best way of course it's just a way.
And we'll go through any errors I had or any big problems I had like I just did.
With that in mind though the next episode will almost certainly be another game of life introducing a few improvements to the system.
Like reading writing the fields out to files, I would also try and figure out how to make it more graphical and anything else I think it needs.
After that we will probably be moving on to a password generator by picking three words from a dictionary.
Not the most secure password I know but hopefully a little bit more memorable for some people.
Some of you will know I work with a local Cub Scout pack here in town and they keep forgetting passwords and I keep having to reset them.
So hopefully a three word password will be long enough to prevent brute force attacks.
We'll not be in the dictionary to avoid dictionary attacks, at least the amalgam of all three words won't.
And we'll still be memorable enough that I don't have to spend what seems to be half my life recessing passwords.
After that I'm not really sure. I have had a few suggestions from a few people, perhaps I suggested by one of my listeners.
We will do a name generator which uses some internet access to make it a name that sort of sounds like something else.
A good example of this is Professor Snape in Harry Potter Snape sounds a bit like Snake.
And that ties in with Slytherin. Slytherin, Slytherin and so on.
Well that's about it for now, apologies for the lateness of this episode.
I could sit and explain how I had immigration to work to do, including being finger print and then photographed or how Mother's Day got in the way.
But the simple fact is I could have found the time I had I wanted to.
By I'm beginning to sound like Dave Yates now.
Okay time to end the show.
Thank you for listening. If you have any questions you can email me at zokosoro at gmail.com.
That's xray osca kilo echo Sierra osca Romeo uniform at gmail.com.
Or you can visit me at zoop.org, xray osca kilo echo, period osca Romeo golf.
And you can give me feedback through there.
Thank you again for your time. You've been listening to Huckbub already.
Thank you for listening to Huckbub the Gradio.
HPR is sponsored by caro.net, so head on over to CARO.nc for all of those meetings.
Thank you.