| | | |
hello world move
|
italic
```
Well trees in the world are actually the other way around haha. Leave it to programmers to not know how to make a tree :)
```
italic
|
hello world move <i>
| | | |
Name Year <mark> <h1> <b> <marquee>
| | | | | |
<th> <th> <td> <td> <td> <td>
\ / \ / \ /
\/ \ / \ /
<tr> <tr> <tr>
\ | /
\ | /
\ | /
\ | /
\ | /
\ | /
<table>
|
<body>
|
<html>
```
But you can see how all things that have the same parent are related, like brothers and sisters.
This is very important, we will spend the next week thinking about it as well.
[DAY-21] HTML - View Source
Browsers on laptops or pcs will allow you to rightclick on any page and then click on View page source
, this will show you the HTML of the page your are looking at.
Open https://archive.org then right click on the pager and then click on View page source
.
We will spend the rest of the day looking at some page sources
https://archive.org
https://www.spacejam.com
https://www.asciiart.eu/
https://www.wikipedia.org
https://www.gutenberg.org/
https://digitalcomicmuseum.com/
https://www.terrypratchettbooks.com/
https://www.goodreads.com/
[DAY-22] HTML - Inspect
Make new html file and write the following example:
```
Right click on this page, click Inspect and then go to Console.
```
Open the file and then click F12, or right click on the page and click Inspect. You will see the logs.
This will open the developer tools of your browser, you will be able to see the console, where you can run small programs or see the errors and the logs of the current page. Try writing 12312*18237978123
in the console and see the result.
In the inspector you can also modify the HTML that you see. This wont modify the actual page on the server you are downloading from, but you can try things to see how they would look. There are actually many scammers that use this method to lie to people as if they are giving them money, or they say 'I will teach you how to add 10000 robux to your account if you pay me 5$' and they just show you how to inspect and edit the html you see. This does not actually give you robux of course, it just modifies your local version of the html to show different value and after you reload the page you will see the old value.
Lets try it. Make a new file with this content:
```
Your Robux Balance is: 0$
```
Open the file and then right click on 0$
and click inspect. Then you will see <b>0$</b>
if you double click on it, you will be able to change it, and you will see the new version. Now reload the page, and you will see the old value is back.
[DAY-23] HTML - Images
To show an image you need the img
tag, and give it src
attribute with the address of the image, for example if I want to display https://picsum.photos/id/237/200/300 I have to do type it like this:
```
```
Lets put the images in a table:
```
```
Now of course we can have img
in a
, try this:
```
```
Now you can click on the dog or the nose and it will lead you to the pages you link to.
Is it possible to have img
and text in a
? Well I am glad you asked!
```
```
I even have <br>
in the a
, now you can click either on the image or on the text.
There is one more very important attribute of the img
tag, and this is the alt
attribute, it is used by people who are blind or visually impaired to know what kind of picture is on the page. In our example we can put alt="puppy"
on the puppy picture.
```
Hello, and welcome to my page.
I hope you will like this image.
```
If a blind person visits this page, they use a screen reader that reads most of the text on the page, and if we have alt
attribute on images it will say Image ...
and whatever the value of alt
is, in our case "puppy". So the reader will say:
```
Hello, and welcome to my page. I hope you will like this image.
Image puppy.
```
If you have an image that has no information, like it is just there to make the site pretty, use alt=""
then the screen reader will skip it.
[DAY-24] Licenses
If you take a picture of something you are the owner of that picture, and you can put it on your website and say you have the rights of that picture. It is up to you to decide if people should link to it by deciding what under license you will publish the image. There are many licenses you can choose from, there are some that say 'this picture is free for anyone to do whatever they want' or 'you can republish the picture but you cant make money selling it' or 'you can publish it but not print it in books' etc etc.
Complicated stuff this licensing, but the thing you have to remember, it is up to the creator to decide under what license their work can be distributed.
Some licenses you can check out with your parents:
Creative Commons Licenses CC-BY https://creativecommons.org/licenses/
GPL https://www.gnu.org/licenses/gpl-3.0.en.html
MIT License https://opensource.org/licenses/MIT
Apache License https://www.apache.org/licenses/LICENSE-2.0
Public Domain https://en.wikipedia.org/wiki/Public-domain-equivalent_license
Copyright https://en.wikipedia.org/wiki/Copyright
When you want to use someone else's work and it is not clear what license it uses, it is best to ask them. At least that is what I do. People are usually nice and they give me permission to use their work.
It is somewhat controversial what is the right way forward, which license to use and what is the best for you and for the world. Ask to your parent about what happens when you take a picture of a painting of a picture of a video and then you edit the video to include the picture you took in it..
Check out https://tldrlegal.com/ for super short description of licenses
[DAY-25] Touch Typing
relax and spend the day touch typing
[DAY-26] HTML - Title
```
THIS IS SPARTA
```
Usually bodies have a <head>
hehe.
In html in the head
tag you can put things that will help the browser. For example, what is the title
of this page? or what language is this page? Who is the author of this page? etc..
You can also put there some style, changing the body's background color, or the color of the text in the h1
or p
:
```
some title
Hello Universe
hello world
```
The language we use inside the style
tag is called CSS
, and it is quite simple (on its surface). We wont get deep into it for a while, but if you are interested check out at https://developer.mozilla.org/en-US/docs/Web/CSS
You see how in certain tags we can use different language, not html, like in <style>
we use CSS, in <script>
we use JavaScript, we are going to do more work with it soon, but you can check out at https://developer.mozilla.org/en-US/docs/Web/JavaScript
[DAY-27] HTML - Fun (JS)
Many buttons
```
🤖
```
Replicator
```
🤖
```
Canvas
```
```
The last one is quite crazy! But I am sure you will like the result when done.
[DAY-28] Print; Functions; While; Variables; Conditions
Make a new file form IDLE, and write in it:
print("Hi!")
Hit F5 and enjoy!
Your first(or second) python program.. Quite useless, but nevertheless. A program is a program!
print()
is called a function, functions are kind of mini useful programs, this one will print whatever you tell it. In this case print("Hi!")
will output Hi!
. Pretty amazing, I hope one day to explain to you what goes into showing a character on your screen. Remind me to show you Ben Eater's 6502 videos when you grow up.
"Hi!"
is a string, strings are just series of characters, you can make them in python with "something"
or 'something'
, either single quotes or double quotes.
while True:
print("Hi!")
while True
that means forever. so you will see:
```
Hi!
Hi!
Hi!
Hi!
Hi!
Hi!
Hi!
Hi!
...
```
Hi forever.
while 1 == 1:
print("Hi!)
1 == 1
is also True, so this is the same as while True
So while <condition>
will keep running the code inside it, while the condition holds true, which in the case of 1 == 1
will always be the case.
while True:
zzz = input("what is your name: ")
print(zzz)
input
asks you to type something, and it returns whatever you typed.
zzz = input(....)
takes whatever input returns, and puts it into memory that we can use later. zzz
is just a name I picked so I can refer to this value later in the program, in this case on the next line when I do print(zzz)
print(name)
prints whatever is in the memory pointed by zzz
.
zzz
is called a variable
, you can choose the names of your variables, and zzz
is surely a poor name, because if I use it 100 lines later in the code, I will forget what kind of information it stores, so usually we give names of the variables that make sense, for example:
while True:
name = input("what is your name: ")
print(name)
A group of statements with common parent, is called code block , in python we use spaces to say what belongs where, so the closest while,for,if,elif,else
going up is the parent.
while True:
name = input("what is your name: ")
print(name)
Will throw an error: IndentationError: unexpected indent
because it makes no sense, there is no valid parent to print
, This is quite unique in python, most other languages make code blocks with {}
, but python makes it prettier and easier to read by using indentation (the spaces/tabs). print(name)
has 4 spaces, while name = input..
has 2 spaces, so python expect everything in the while:
to have 2 spaces unless a new block starts.
while True:
name = input("what is your name: ")
if name == "pikachu":
print(name)
This works fine, print(name)
now has valid parent that also has a parent.
while True:
| \
| \
| \
| \
if: name = input
|
print(name)
while True
has two children, name = input ..
and if name == ..
so they must have same indentation, then if ..:
also expects a code block, so the children of if name == ..
need to have one more indentation to whatever indentation the if
had.
Anyway..
Don't worry too much about it, just don't panic when you see IndentationError
, and I can promise you, you will see a lot of those. Look at where you got the spaces wrong, and if the block has correct parent.
You have seen by now in JavaScript we use {}
to group statements into blocks.
if (name == "pikachu") {
console.log("pikaaaachuuuuu")
console.log("evolutiooonn!")
}
Now lets break out of the loop!
while True:
name = input("what is your name: ")
if name == "pikachu":
break
if name == "pikachu":
will run the code inside if
if whatever is in the name
variable is equal to the string "pikachu". In this case its only 1 instruction inside it, the break
instruction.
break
breaks out of the closest while
loop, so basically this program will ask what is your name until you type pikachu. It is a bit boring because we never actually print what you typed.
```
while True:
name = input("what is your name: ")
print(name)
if name == "pikachu":
break
print("DONE")
```
There we go, now it will ask you to type a name, it will print whatever name you typed, and then it will check if the name is equal to "pikachu" it will break the while loop and stop asking. We can actually write this program in a different way. After you break out of the loop, it just continues to execute the program below, in this case will print DONE.
```
name = ''
while name != "pikachu":
name = input("what is your name: ")
print(name)
print("DONE")
```
MAGIC!
we start by making name equal to empty string, a string with no characters, and then we check is the statement name != "pikachu"
True? If this is True we will execute the code inside the while loop, after the last instruction in the loop, the program jumps back to while name != "pikachu"
and checks again is name still not equal to "pikachu"? if the statement is False it will not run the code inside but will continue, in the above example it will print DONE, because this is the first thing after the while loop.
Lets make a more complicated one, this one will ask you what is your name, and if you answer pikachu will print pikaaaaaaachuuuuu and stop, any other answer it will print "Hello, " + answer, so if you type "Jane" it will show "Hello, Jane" and it will ask again.
while True:
name = input("what is your name: ")
if name == "pikachu":
print("pikaaaaaaachuuuuu")
break
else:
print("Hello, " + name)
In python you can add two strings, if you type "charmander" for name, x = "Hello, " + name
will make x to be equal to "Hello, charmander". You can't do "hello" - name
, but you can do "hello" * 5
and get "hellohellohellohellohello".
while,if,else,break
are keywords, kind of like <html>
and <body>
, <h1>
etc, those are coming from python itself. There are not many python keywords, for reference, this is the complete list:
```
False
True
None
and -> name == "pikachu" and age == "33"
or -> name == "pikachu" or name == "charmander"
not -> not name == "pikachu" is the same as name != "pikachu"
for -> used if you know how many times you want to do something
while -> do something until condition is True
break -> break out of the for or while loop
continue -> go to the start of the while/for loop and continue from there
if -> if something is true
elif -> else if something else is true
else -> else do this
in -> checks if something is in somethhing else, e.g. "pika" in name
def -> make a function
as
assert
async
await
class
del
except
finally
from
global
import
is
lambda
nonlocal
pass
raise
return
try
with
yield
```
THATS THE WHOLE LANGUAGE, there are no more keywords.
[DAY-29] Print; If
```
print("Welcome to the forest!")
print("This is a world of magic and wonders. You are on a cross road, you can go north east south or west.")
print("South leads to the swamps, where the aligators live")
print("West leads to the mountains, where the yeti lives")
print("North leads to the jungle, where the tigres live")
print("East leads to the desert, where the meerkats live")
print("")
what = input("what would you do next: ")
if what == "east":
print("Welcome to the desert")
print("It is very hot, and you need remember to put sun screen.")
print("Oh, you remember to put your hat as well.")
print("In the distance you see a meerkat approaching.")
print("What would you do? Run or Fight the meerkat?")
print("")
what = input("what would you do next: ")
if what == "run":
print("You start running, and the meerkat is super fast, it catches you in no time.")
elif what == "fight":
print("You try to fight it, but turns out it was friendly and wants to become your friend.")
print("What would you do?")
print("")
what = input("Do you want to be its friend: ")
if what == "yes":
print("Great! Now the meerkat wants to introduce you to his family.")
elif what == "no":
print("The meerkat starts crying!")
else:
print("I dont understand: " + what)
```
That is a lot of typing.
In python there are few very important things. First even though it doesn't look like it, it is actually a tree, like HTML tree. The parent of print("The meerkat starts crying!")
is elif what == "no":
|
|
if what == "east"
|
/ | \
/ | \
/ | \
/ | \
/ | \
if else elif
what == "run" | what == "fight
| | |
print print / \
/ \
/ \
/ \
if elif
what == "yes" what == "no"
| |
[ ... ] [ ... ]
Lets discuss another example:
a = "he"
b = "ll"
c = "o"
if a == "he":
if b == "ll":
if c == "o":
print("hello")
Can you tell who is the parent of who?
BTW, you can also use and
, or
and not
when you want to see if something is True
a = "he"
b = "ll"
c = "o"
if a == "he" and b == "ll" and c == "o":
print("hello")
[DAY-30] Functions; Lists
Our game is quite limited, and a quick step to improve it is to make you ask where you want to go until you pick one of the options.
```
def ask(possible_answers):
answer = ''
print("---") # print empty line
while True:
answer = input("> What would you do next: ")
if answer not in possible_answers:
print("> try again, it must be one of:", possible_answers)
else:
return answer
print("Welcome to the forest!")
...
what = ask(["east","west","north","south"])
if what == "east":
print("Welcome to the desert")
#...
what = ask(["run","fight"])
if what == "run":
print("You start running, and the meerkat is super fast, it catches you in no time.")
elif what == "fight":
print("You try to fight it, but turns out it was friendly and wants to become your friend.")
# ...
what = ask(["yes","no"])
if what == "yes":
print("Great! Now the meerkat wants to introduce you to his family.")
elif what == "no":
print("The meerkat starts crying!")
elif what == "north":
print("Welcome to the north pole, it is super cold here.")
```
ask
is a function, just like print
or input
, it will keep asking you > What would you do next:
until the answer you type is in the possible_answers list, and if it is it will return it to wherever it is called from. So when we have zzz = ask(["yes","no"]
the value of zzz
will be whatever is returned from ask
. Same as name = input("what is your name)
will put in name
whatever is returned from input
which is whatever you typed on your keyboard.
To make a function in python you need to use the def
keyword.
```
def sum(a,b):
return a + b
r = sum(1737,1231231)
print(r)
```
Whatever is between def
and (
is the name of the function, in the above example its sum
. Between ()
you put in the name of the variables you expect to use when someone calls your function. I want to sum two numbers, I dont know what the numbers are, so I just make two variables a, b
and expect whoever calls my function to give me the numbers, like r = sum(1737,1231231)
[DAY-31] Functions; If; Random; Lists
FIGHT TO THE DEATH!
```
import random
import time
def fight(playerHP, enemyHP, enemy_name):
# fight to the death!
while playerHP >= 0 and enemyHP >= 0:
punch = random.randint(0, 20)
if random.choice(["player","enemy"]) == "player":
playerHP = playerHP - punch
print("<"+enemy_name+"> hits you for " + str(punch) + ", " + str(playerHP) + " left")
else:
enemyHP = enemyHP - punch
print("you hit <"+enemy_name+"> for " + str(punch) + ", " + str(enemyHP) + " left")
time.sleep(1)
return playerHP
fight(100, 50, "meerkat")
```
import
imports a module.
random
and time
those are the modules
you import, modules are just a group of functions that you can use, for example time.sleep(1)
makes python sleep for 1 second, it calls the function sleep()
in the time
module. random.choice()
you can give a list of things to choose from, and it will randomly select one of the list. random.randint(0,20)
means give me a random number between 0 and 20.
str
is needed to convert integer to string, because 1 is not the same as "1", "1" is actually the ASCII value of the character 1, so somehow we have to convert the raw number 1 to ASCII code 61, and str()
does that.
lets use it now in our dungeon game
```
import random
import time
def ask(possible_answers):
...
def fight(playerHP, enemyHP, enemy_name):
...
...
health = 100
what = ask(["east","west","north","south"])
if what == "east":
...
what = ask(["run","fight"])
if what == "run":
...
elif what == "fight":
meerkatHP = 50
health = fight(health, meerkatHP, "meerkat")
if health <= 0:
print("GAME OVER! THE MEERKAT BEAT YOU")
else:
print("You won against the meerkat, you have " + str(health) + " HP left))
```
[DAY-32] Lists; While
Today you have to make only two programs:
```
bad = ["broccoli","chocolate","pineapple"]
while True:
food = input("what is your favorite food: ")
if food in bad:
print("ewwwww I hate " + food)
else:
print("yumm, I love " + food)
```
And the second one:
bad = ["broccoli","chocolate","pineapple"]
good = ["pizza","popcorn"]
while True:
food = input("what is your favorite food: ")
if food in bad:
print("ewwwww I hate " + food)
elif food in good:
print("yumm, I love " + food)
else:
print("I have never tried " + food)
Great job!
Spend the rest of the day touch typing.
[DAY-33] For
for
does something number of times, if I want to print the numbers from 0 to 99, I could do:
for i range(100):
print(i)
or
for i in range(10, 20):
print(i)
will print the numbers from 10 to 19
colors = ["red","green","blue"]
for color in colors:
print(color)
will print each of the elements in the list. If you want to print each character of a string in a similar way you can do:
name = "jack"
for c in name:
print(c)
prints:
j
a
c
k
[DAY-34] Love Tester
```
def love_test(a,b):
sum = 0
for c in a+b:
print(c + ': ' + str(ord(c)))
sum += ord(c)
print('sum is:' + str(sum))
return sum % 100
while True:
nameA = input("first name: ")
nameB = input("second name: ")
print("love test: " + str(love_test(nameA,nameB)))
```
ord
takes the ascii code of a character.
%
is the remainder, so 109 % 100
is 9, basically what is left after you can cleanly divide two numbers, 812 % 100
is 12, you can fit 100 in 819 exactly 8 times, and then there is 12 left, this 12 is the remainder.
So in this program we take two names into the variables nameA
and nameB
and then we give them to the love_test function, which sums the ascii code of nameA+nameB
, and then returns the remainder of 100.
first name: jack
second name: jane
j: 106
a: 97
c: 99
k: 107
j: 106
a: 97
n: 110
e: 101
sum is:823
love test: 23
BTW, now you know how those "professional" love testers are made, so if you use https://www.lovetester.nl/ or something similar.. don't read too much into the result. You can easily tweak it to do whatever you want.
[DAY-34] Touch Typing
Whoaa it has been a difficult week.
Relax with some touch typing.
[DAY-35] Lists; While; Continue
This week there will be less talking and more programming.
Make a program to help you to decide what to do:
```
import random
possible = ["nothing"]
while True:
x = input("What would you like to do: ")
if x == "done":
break
else:
possible.append(x)
what = random.choice(possible)
print("possible choices: ")
print(possible)
print("the magic 8 ball decided: " + what)
```
Make a program to help you multiply two numbers:
while True:
a = int(input("first number: "))
b = int(input("second number: "))
print(a, "*", b, "=", a*b)
Here I do a little trick, and make print print numbers instead of making them into string by passing it as separate parameters to the print function. otherwise I have to do:
```
while True:
a = int(input("first number: "))
b = int(input("second number: "))
print(str(a) + " " + str(b) + "=" + str(a b))
```
What is your spy name?
name = input("what is your name: ")
print("Your spy name is: " + name[0] + name[1])
You can get individual characters from string by picking them up with []
so if name is 'jane' then name[0]
is 'j'
Make a calculator
while True:
a = int(input("first number: "))
b = int(input("second number: "))
op = input("operation * / + :")
result = 0
if op == "*":
result = a * b
elif op == "/":
result = a/b
elif op == "+":
result = a+b
else:
print("I dont understand " + op)
continue
print(a,op,b,'=',result)
See how we use continue
to not print a result if we don't understand the operation. continue
jumps to the beginning of the loop.
[DAY-36] While; Range; Functions
Print the numbers from 0 to 9 FOREVER
while True:
for i in range(10):
print(i)
Print each character of a string:
name = input("what is your name: ")
for c in name:
print(c)
Sum the numbers from 0 to 99
```
sum = 0
for i in range(100):
sum = sum + i
print(sum)
```
Print all the prime numbers from 0 to 100:
```
def is_prime(n):
if n == 1 or n == 0:
return False
for i in range(2, n):
if n % i == 0:
return False
return True
for i in range(100):
print(i, is_prime(i))
```
multiply two numbers:
```
a = int(input("number 1: "))
b = int(input("number 2: "))
c = a * b
print(c)
```
Timer:
```
import time
s = int(input("how many seconds: "))
for i in range(s):
print(i)
time.sleep(1)
print(s, "SECONDS ARE OVER")
```
[DAY-37] While; Functions
Clock
```
import datetime
import time
import os
while True:
os.system('clear')
now = datetime.datetime.now()
print(now)
time.sleep(1)
```
Calendar
```
def show(calendar):
for row in calendar:
for day in row:
print(day,end=' ')
print('')
june = [
['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
[' ', ' ', ' 1', ' 2', ' 3', ' 4', ' 5'],
[' 6', ' 7', ' 8', ' 9', '10', '11', '12'],
['13', '14', '15', '16', '17', '18', '19'],
['20', '21', '22', '23', '24', '25', '26'],
['27', '28', '29', '30', ' ', ' ', ' '],
]
show(june)
```
Growing list of food.
```
food = []
while True:
what = input("what is your favorite food: ")
food.append(what)
print(what)
```
Guessing game
colors = ["red","green","blue"]
score = 0
while True:
guess = input("guess a color: ")
if guess in colors:
print("good guess! I like " + guess)
else:
print("nop, I dont like " + guess)
Guess again
```
def is_in_list(list,what):
for element in list:
if element == what:
return True
return False
colors = ["red","green","blue"]
score = 0
while True:
guess = input("guess a color: ")
if is_in_list(colors, guess):
print("good guess! I like " + guess)
else:
print("nop, I dont like " + guess)
```
[DAY-38] Strings
What was your name again?
for i in range(10):
name = input("what is your name: ")
print(i)
print(name)
First and last letter:
name = input("what is your name: ")
print("first letter: " + name[0])
print("last letter: " + name[len(name)-1])
to get the last letter we have to count however letters are in the whole name, so len(name)
will return 4 for 'jane' and it counts from 1
```
len("jane"):
j a n e
1 2 3 4
len("ja")
j a
1 2
```
but when we are using [0]
to get to specific character from a string or element from a list, it counts from 0, so
```
j a n e
0 1 2 3
name = "jane"
name[0] is j
name[1] is a
name[2] is n
name[3] is e
len(name) is 4 (because len counts from 1)
so name[len(name) - 1], is name[4 - 1] or name[3] which is the last letter
```
Make a Line
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
line(20, '#')
line(30, '*')
line(40, '_')
```
Make a triangle
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
for i in range(100):
line(i,'*')
print('')
```
Make a beam
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
for i in range(50):
line(i, ' ')
line(i, '*')
print('')
```
Make a box
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
def box(width,height,symbol):
for y in range(height):
line(width,symbol)
print('')
box(16,20)
box(10,20,'#')
box(15,13,'*')
```
[DAY-39] Touch Typing
Do some touch typing.
[DAY-40] Functions; Strings; Range
Make inverse beam
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
count = 50
for i in range(count):
line(count - i, ' ')
line(i, '*')
print('')
```
Make a tree
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
count = 50
for i in range(count):
half = int((count-i)/2)
line(half , ' ')
line(i, '*')
print('')
```
Inverse
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
count = 50
for i in range(count):
line(count-i, '*')
print('')
```
Inverse tree
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
count = 50
for i in range(count):
half = int(i/2)
line(half , ' ')
line(count-i, '*')
print('')
```
Art
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
while True:
count = 10
for i in range(count):
line(count-i, '*')
print('')
for i in range(count):
line(i, '#')
print('')
```
Looks so pretty!
```
**
*
**
*
```
[DAY-41] Basics of Basics
More Art
```
import random
def line(width, symbol):
for x in range(width):
print(symbol,end='')
symbols = ['*','#','%','^','&']
while True:
count = random.randint(5,80)
symbol = random.choice(symbols)
for i in range(count):
line(count-i, symbol)
print('')
symbol = random.choice(symbols)
for i in range(count):
line(i, symbol)
print('')
```
Staircase
```
def line(width, symbol):
for x in range(width):
print(symbol,end='')
count = 100
for i in range(0, count, 5):
line(i, '*')
print('')
```
Range is so cool, and you didnt even notice!
Try this:
for i in range(0, 100, 10):
print(i)
it will print
0
10
20
30
40
50
60
70
80
90
so every 10th number, now try:
for i in range(0, 100, 5):
print(i)
and
for i in range(0, 100, 2):
print(i)
Of course you dont have to start counting from 0:
for i in range(50, 100, 2):
print(i)
Do some touch typing if there is time left.
[DAY-41] Lists; If; While
```
import random
words = ["pizza","pikachu","ball","pokemon"]
while True:
word = random.choice(words)
guessed = []
life = 10
while True:
print('*' * 10, ' HANGMAN ', '*' * 10)
matching = 0
for c in word:
if c in guessed:
print(c,end='')
matching = matching + 1
else:
print('-',end='')
print('')
print('*' * 31)
if matching == len(word):
print('congratz you won!')
break
character = input("guess a character: ")
if character in word:
guessed.append(character)
else:
print(character + " is not in the word, " + str(life) + ' lives left')
life = life - 1
if life == 0:
print('you lost!')
break
```
[DAY-42] Lists; Functions; Grid; While
World without a player
```
def render(world):
for row in world:
for col in row:
print(col,end=' ')
print('')
def empty():
return [
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
]
world = empty()
render(world)
while True:
row = int(input("which row (count from 0): "))
col = int(input("which column (count from 0): "))
world[row][col] = 'x'
render(world)
```
World with a player
```
def render(world):
for row in world:
for col in row:
print(col,end=' ')
print('')
def empty():
return [
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
]
world = empty()
player_row = 0
player_col = 0
world[player_row][player_col] = 'x'
render(world)
while True:
direction = input("which direction: ")
world[player_row][player_col] = '*'
if direction == "up":
player_row = player_row - 1
elif direction == "down":
player_row = player_row + 1
elif direction == "left":
player_col = player_col - 1
elif direction == "right":
player_col = player_col + 1
world[player_row][player_col] = 'x'
render(world)
```
[DAY-43] If; Range
Even and Odd
number = int(input("give me a number: "))
if number % 2 == 0:
print("this number is even")
else:
print("this number is odd")
Fizz Buzz
Print integers 1 to N, but print "fizz" if an integer is divisible by 3, "buzz" if an integer is divisible by 5, and "fizzbuzz" if an integer is divisible by both 3 and 5.
```
n = 100
for i in range(1,n+1):
if i % 5 == 0 and i % 3 == 0:
print("fizz buzz")
elif i % 3 == 0:
print("fizz")
elif i % 5 == 0:
print("buzz")
else:
print(i)
```
or different version
```
n = 100
for i in range(1,n+1):
fizzbuzzing = False
if i % 3 == 0:
fizzbuzzing = True
print("fizz", end = '')
if i % 5 == 0:
fizzbuzzing = True
print("buzz", end = '')
if not fizzbuzzing:
print(i, end = '')
print('')
```
There are many ways to write this, lets just have fun.
```
n = 100
numbers = []
first make empty list with 100 elements
for i in range(1, n+1):
numbers.append('')
then fill in the fizzes
for i in range(1, n+1):
if i % 3 == 0:
numbers[i-1] += 'fizz'
then fill in the buzzess
for i in range(1, n+1):
if i % 5 == 0:
numbers[i-1] += 'buzz'
then fill in the numbers
for i in range(1, n+1):
if numbers[i-1] == '':
numbers[i-1] = i
then we print it
for x in numbers:
print(x)
```
Haha this is a funny way to make fizzbuzz. See first it puts fizz if you can divide it by 3, and then buzz if you can divide it by 5, but if there was already fizz there it will just add if with +=
, so it automatically works to put fizzbuzz for 15.
[DAY-44] Lists
Reviews
```
reviews =[5,3,2,4,1,2,3,4,2,1,5,5,3,2]
sum = 0
for r in reviews:
sum += r
rating = sum / len(reviews)
print(str(rating) + "⭐ out ot 5")
```
Icecream Maker
```
import random
flavors = ['vanilla','chocolate','blue','banana','bluberry']
flavorA = random.choice(flavors)
flavorB = random.choice(flavors)
print(flavorA + " + " + flavorB)
```
Spend the rest of the day touch typing.
[DAY-45] Lists; Functions
Different touch typing
```
import random
vowels = ['a', 'e', 'i', 'o', 'u', 'y']
consonants = ['b','c','d','f','g','h','j','k','l','m','n','p','q','r','s','t','v','w','x','z']
def make_word(n_chars):
word = ''
for i in range(n_chars):
if random.randint(1,100) < 40:
word += random.choice(vowels)
else:
word += random.choice(consonants)
return word
def make_sentence(n_words):
sentence = ''
for i in range(n_words):
sentence += make_word(random.randint(3,6))
sentence += ' '
# this will remove the last element from the sentence string
# so we dont have empty space in the end
return sentence[:-1]
while True:
sentence = make_sentence(random.randint(10,20))
print(sentence)
guess = input('write the sentence: ')
if guess != sentence:
print("SORRY")
else:
print("GOOD JOB")
```
spend the rest of the day trying it out
[DAY-46] Basic Turtle
Some turtle!
import turtle
turtle.circle(30)
Many circles
import turtle
for i in range(30):
turtle.circle(i)
Bigger circles
```
import turtle
turtle.color("blue")
for i in range(30):
turtle.circle(50 + i)
```
Smile
```
import turtle
turtle.color("blue")
turtle.circle(100)
turtle.penup()
turtle.goto(60,120)
turtle.pendown()
turtle.circle(20)
turtle.penup()
turtle.goto(20,120)
turtle.pendown()
turtle.circle(20)
turtle.penup()
turtle.goto(-30,20)
turtle.pendown()
turtle.right(45)
turtle.circle(20, 120)
```
[DAY-47] Range; While
Try to make a program that prints a symbol N times, where N is coming from the user input.
Try by yourself.
[DAY-48] Strings; Functions
How big can a string be?
Your computer has limited amount of memory, usually 8 gigabytes, that is a lot of memory. 8 * 1024 megabytes * 1024 kilobytes * 1024 bytes, so 8589934592 bytes. What if we make python create a string with more characters than memory?
NB: before you try that, save all your files because you might have to restart your computer, depending on the operation system version.
try_me = 'x' * (8 * 1024 * 1024 * 1024)
print(len(try_me))
If you can not press any buttons after that, or the mouse is not working, you will have to hold the power button for 10 seconds to turn your computer off and then turn it back on.
lets try another thing
```
def forever(n):
print(n)
forever(n+1)
forever(1)
```
this will throw a weird error
RecursionError: maximum recursion depth exceeded while pickling an object
Don't be afraid of it, every time you call a function, a little bit of memory has to be used, and this memory is released when the function returns, now imagine a function that calls itself, so you get this:
forever(1)
forever(1+1)
forever(1+1+1)
forever(....)
So the memory for those function is never released, and this error just says, you cant go and call so many functions that never return. But you will see on your system you can have around 10000 functions that are waiting for their child to return.
Play with it a bit.
```
def one(n):
print("one", n)
two(n+1)
def two(n):
print("two", n)
one(n+1)
one(1)
```
[DAY-49] List; Dictionaries
```
import random
game = [
['What is the capital of France?','Paris','London','Paris','Berlin','Tokyo'],
['What is the capital of Japan?','Tokyo','London','Paris','Berlin','Tokyo'],
["What is Jane's favorite food?",'Popcorn','Pizza','Popcorn','Cucumber','Sushi']
]
while True:
quiz = random.choice(game)
print(quiz[0])
for index, possible in enumerate(quiz):
if index >= 2:
print(possible)
answer = input('What is your answer: ')
if answer == quiz[1]:
print("✨✨✨ CORRECT ✨✨✨")
else:
print("INCORRECT")
```
see enumerate
is quite handy, you get the index of something and its value while you are doing the for
x = ['a','b','c','d']
for index ,element in enumerate(x):
print(index)
print(' ' + element)
make it easier to read:
```
import random
QUESTION_IDX = 0
ANSWER_IDX = 1
game = [
['What is the capital of France?','Paris','London','Paris','Berlin','Tokyo'],
['What is the capital of Japan?','Tokyo','London','Paris','Berlin','Tokyo'],
["What is Jane's favorite food?",'Popcorn','Pizza','Popcorn','Cucumber','Sushi']
]
while True:
quiz = random.choice(game)
print(quiz[QUESTION_IDX])
for index, possible in enumerate(quiz):
if index >= ANSWER_IDX+1:
print(possible)
answer = input('What is your answer: ')
if answer == quiz[ANSWER_IDX]:
print("✨✨✨ CORRECT ✨✨✨")
else:
print("INCORRECT")
```
See how just using QUESTION_IDX and ANSWER_IDX instead of 0 and 1 it is easier to read. Now lets try a completely different way:
```
import random
game = [
{
"question": "What is the capital of France?",
"answer": "Paris",
"possible": ['London','Paris','Berlin','Tokyo'],
},
{
"question": "What is the capital of Japan?",
"answer": "Tokyo",
"possible": ['London','Paris','Berlin','Tokyo'],
},
]
while True:
quiz = random.choice(game)
print(quiz["question"])
for p in quiz["possible"]:
print(' --> ' + p)
answer = input('What is your answer: ')
if answer == quiz["answer"]:
print("✨✨✨ CORRECT ✨✨✨")
else:
print("INCORRECT")
```
This is just another way to do it, see in the list we can store those strange things. We will talk about them in a couple of weeks, I just wanted to show you how clean it is when
[DAY-50] Lists; If
Print the odd numbers from 0 to 999
for i in range(1000):
if i % 2 != 0:
print(i)
rock paper scissors
```
import random
game = ["rock","paper","scissors"]
rounds = 3
nameA = input("name player A: ")
nameB = input("name player B: ")
winsA = 0
winsB = 0
for i in range(rounds):
playerA = random.choice(game)
playerB = random.choice(game)
print("ROUND: " + str(i + 1))
print("playerA : " + playerA)
print("playerB : " + playerB)
if playerA == playerB:
print(" > DRAW")
elif playerA == "rock" and playerB == "paper":
print(" > " + nameB + " WINS")
winsB += 1
elif playerA == "rock" and playerB == "scissors":
print(" > " + nameA + " WINS")
winsA += 1
elif playerA == "paper" and playerB == "rock":
print(" > " + nameA + " WINS")
winsA += 1
elif playerA == "paper" and playerB == "scissors":
print(" > " + nameB + " WINS")
winsB += 1
elif playerA == "scissors" and playerB == "rock":
print(" > " + nameB + " WINS")
winsB += 1
elif playerA == "scissors" and playerB == "paper":
print(" > " + nameA + " WINS")
winsA += 1
else:
print("WTF " + playerA + " " + playerB)
print("---")
print(nameA + " has " + str(winsA) + " points")
print(nameB + " has " + str(winsB) + " points")
if winsA > winsB:
print(nameA + " IS THE WINNER")
elif winsA < winsB:
print(nameB + " IS THE WINNER")
else:
# this will show only if we have even number of rounds
print("THERE IS NO WINNER")
```
[DAY-51] Internet Awareness - Scams/Viruses
Today is an important day, its Internet awareness day.
Make the most expensive drone on amazon.com cost 0$, or even -5$. As we did in the first week, open inspect click on the mouse selector (or press Control+Shift+C) and click on the price you want to change, then double click on the HTML and change it to whatever you want.
After you are done reload the page to see it is not actually changed.
Now do that on roblox, make it look like you have 999999 robux.
Go to google and search for Speed up your internet connection
, go over the websites one by one with your parent, and observe, look at many many scams, some are very easy to fall into, some are obvious.
Open youtube.com, search for 'free energy hack' watch some of the videos, then search for 'electroboom free energy' and watch Mehdi explain why it is a scam. Search for 'be carefull what you order from facebook ads' Pleasant Green and watch how he explains a scam with ads to buy a cool looking helmet.
See the internet is a place, where you can find great things, like electroboom and pleasant green or veritasium or vsauce, but also where there are horrible things, like people selling garbage for 30$. Or people claiming
Now with your parent, search on youtube for 'how to hack in roblox' and look at the scame, how people want to install something so they can steal your password.
[DAY-52] Internet Awareness - How Login Works
Ok now for something more serious!
Just a quick intro into cookies, when you login to a website, it stores a piece of information on your computer called a cookie, and with every request you make to the website after it sends this cookie, the website can also tell you to replace the cookie. This is how websites know you are logged in, after they check your user and password they send you a cookie with a secret value, that you use for every request, they store that value usually in a database (kind of like huge huge excel sheet, that you can quickly search in), and look it up to see if it is valid.
So imagine websites have a table like so:
|username|password|
|-|-|
|jane|123456|
|john|blabla|
It is a bit more complicated than that, because they don't store the password but "encrypted" version of the password, so instead of 123456 (which is a horrible password btw), they store the result of a cryptographic hash function, hash(salt + '___' + password), and salt is used so that the attacker has to get both the usernames, the encrypted passwords and the code that joins them in order to extract a password using some bruteforce methods.
A cryptographic hash function is like a machine where you put in a lego castle in, and it will spit out exactly 8 pieces (ot 32 or whatever the function is), and there is no easy way for you to guess what kind of castle you put in it, but you know that always the same castle will spit out the same 8 pieces.
So in reality the excel sheet looks a bit like this:
|username|encrypted password|salt|
|-|-|-|
|jane|4c87d9b2ecfbd99c483aedfae8045fe578912e63|someRandom123|
|john|065ce4538c7c51687270972babdeaa986f3ce1bd|someRandom435|
But that is not important, we will use the simple example for our case. When you click 'login' it will send the username and password over the internet, and their server will look in the table for this user and will check if the password matches. If it matches it will insert a row another excel sheet that looks like this:
|username|token|
|-|-|
|jane|bbd0bff806a177f082f3ba2cff33030d335c296e|
then tell your browser, hey set this cookies:
the username for amazon.com is 'jane'
the token is bbd0bff806a177f082f3ba2cff33030d335c296e
So next time when you make a request to amazon your browser will send both the user name and the token, amazon will check in the token table if this token is valid (they have expiration date as well, kind of like a real token), and then it will know you actually logged in, without your password being stored on your browser.
Now lets see how someone can login as you without knowing your password.
Login to amazon. Open chrome in private mode. Open amazon there as well, and see that on one browser you are logged in, on the private mode you are not. Now open the console(press F12) on the logged in browser and type this:
var cookies = []
for (cookie of document.cookie.split(";")) {
cookies.push(cookie.replace(" ", ""))
}
console.log(JSON.stringify(cookies))
This will print all the cookies amazon has set on your browser in a list.
Copy the whole list of cookies, now on the private mode browser's console(press F12 to open the console) type:
var newCookies = ["session-id....." .. .. ] // just paste the whole string from the other browser
for (cookie of newCookies) {
document.cookie = cookie;
}
Paste the whole list there, and refresh the page.
And voila! You are logged in now without typing a password.
So if you give access to somebody to your computer, they can trivially copy your cookies and send them somewhere, and then they can login as you without even knowing your password. In fact this is a very common way to steal someone's account on social media. Ask them to paste a strange code in the console, which is usually base64 encoded
that looks like this:
d = atob('dmFyIGNvb2tpZXMgPSBbXQpmb3IgKGNvb2tpZSBvZiBkb2N1bWVudC5jb29raWUuc3BsaXQoIjsiKSkgewogICAgY29va2llcy5wdXNoKGNvb2tpZS5yZXBsYWNlKCIgIiwgIiIpKQp9CmNvbnNvbGUubG9nKGNvb2tpZXMpCg==')
console.log(d)
eval(d)
You see how it printed your cookies? The thing that runs the code is eval
it is kind of like double clicking on a program, but it will run the code that is inside the string you give it. If you want to see what the code does just run console.log(atob('....'))
this will just decode the base64 encoding into a string you can read. atob
decodes base64 string into the real string, it is kind of like in python ord('a')
gives you 97 and chr(97)
gives you 'a'.
Of course the code that the scammers give you is more sophisticated, it sends the cookies to their database(think excel sheet) via the internet, including all local storage and local session data, and they can just use it after that.
That is why if you open facebook.com and press F12 you will see giant message:
```
STOP STOP STOP
This is a browser feature intended for developers. If someone has told you to copy and paste something here to enable a Facebook feature or "hack" someone else's account, it is a scam and they are trying to access your Facebook account.
```
When you Logout from somewhere, they delete the token on their side, so the next time a request is made, they know you are not logged in anymore. That is why its important to logout if you use someone else's computer to login.
[DAY-53] Basics of the Internet - IP/DNS
The internet is a mess, a mess of things that talk to each other. Each of the things has their own IP address (ip stands for internet protocol), for example open https://1.1.1.1 you see this is a simple ip address of a popular DNS server (dns is a system we use to resolve names into ip addresses, e.g. facebook.com is 31.13.64.35). You can check the ip address by searching 'whats my ip' on google, and because your browser has to connect to google's server and they connect through their IP addresses, so google knows your IP. Of course it is a bit more complicated than that, but for now this will do.
The other most important thing is domain names, like facebook.com and yahoo.com or amazon.de. We need names otherwise everyone will have to remember 31.13.64.35 to open facebook.. which is not easy. To find out the ip of facebook.com you need to ask a .com server about which server is responsible for facebook.com, and then ask this server about what is the ip address of www.facebook.com. The whole system is like a tree.
```
ROOT
"."
/ | \
/ | \
.de .com .io
/ |
amazon /|\
/ | \
/ | \
/ | \
/ | \
amazon netflix yahoo
```
your internet provider gives you your ip address and also a convenient name server to use, you can also use other name servers like 1.1.1.1 or 8.8.8.8, keep in mind, whoever nameserver you use, knows which websites you visit, because you have to ask them about the ip address of each website you visit.
A lot of scammers also ask you to change your dns server, they lie about getting faster internet and etc, but you see, if you ask a scammer's dns server 'what is the ip address of facebook.com', and they say 'well its 12.12.12.12' or whatever their server's address is, they can show you a webpage that looks like facebook, but its theirs, and when you login they can get your password. Remember when you login your browser sends the password to the other server that has to check it, so they can steal it that way.
To prevent this kind of attacks modern browsers use something called HTTPS, or secure http, you see a small closed lock on the address bar, and when you click it it will say 'Connection is secure', that means that it verified that the website you opened is actually the website you think it is. There are ways to attack this as well, but it is not trivial, and someone has to have physical access to your computer to install a new Trusted Certificate Authority (which we will explain way later).
But one more reason to be sus of people using your computer. Not only they can steal your cookies, but they can also install a new Trusted CA, change the DNS and then intercept all your requests.
[DAY-54] Touch Typing
Touch typing day is finally here! Enjoy keybr.com!
[DAY-55] Lists; Functions
Tic Tac Toe
```
def empty_game():
game = [
[' ','a','b','c','d'],
['1','-','-','-','-'],
['2','-','-','-','-'],
['3','-','-','-','-'],
['4','-','-','-','-']
]
return game
def show_game(game):
for row in game:
#[' ','a','b','c','d']
#...
for col in row:
#' '
#'a'
#'b'
print (col, end=' ')
print('')
g = empty_game()
x_or_zero='x'
while True:
show_game(g)
p = input('place ' + x_or_zero + ': ')
if p == 'a1':
g[1][1]=x_or_zero
if p == 'a2':
g[2][1]=x_or_zero
if p == 'a3':
g[3][1]=x_or_zero
if p == 'a4':
g[4][1]=x_or_zero
if p == 'b1':
g[1][2]=x_or_zero
if p == 'b2':
g[2][2]=x_or_zero
if p == 'b3':
g[3][2]=x_or_zero
if p == 'b4':
g[4][2]=x_or_zero
if p == 'c1':
g[1][3]=x_or_zero
if p == 'c2':
g[2][3]=x_or_zero
if p == 'c3':
g[3][3]=x_or_zero
if p == 'c4':
g[4][3]=x_or_zero
if p == 'd1':
g[1][4]=x_or_zero
if p == 'd2':
g[2][4]=x_or_zero
if p == 'd3':
g[3][4]=x_or_zero
if p == 'd4':
g[4][4]=x_or_zero
if p == 'clear':
g = empty_game()
if x_or_zero =='x':
x_or_zero = '0'
else:
x_or_zero='x'
```
Spend the rest of the day playing.
[DAY-56] Functions; If; Random
Trivia game
```
def check(question, answer):
x = input(question + ": ")
if x == answer:
return True
else:
return False
score = 0
if check("which animal lives on the north pole?", "polar bear"):
score += 1
if check("which animal lives in the jungle?", "tiger"):
score += 1
print("your score is: " + str(score))
```
Math test:
```
import random
while True:
a = random.randint(1,10)
b = random.randint(1,10)
r = int(input("what is " + str(a) + " * " + str(b) + "? " ))
if r == a * b:
print("Correct!")
else:
print("Incorrect, the answer was: " + str(a * b))
```
Random characters
```
import random
while True:
x = random.randint(ord('a'), ord('z'))
print(chr(x))
```
[DAY-57] Lists; Functions; Grid
Snake
```
import random
APPLE_SYMBOL = '@'
def render(world):
for row in world:
for col in row:
print(col,end=' ')
print('')
def empty():
return [
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
['-','-','-','-'],
]
def snake_eats_itself(positions, current_col, current_row):
for (col,row) in positions:
if col == current_col and row == current_row:
return True
def place_apple(world):
# just place it on a random square from all possible squares
possible = []
for index_row in range(len(world)):
for index_col in range(len(world[index_row])):
if world[index_row][index_col] == '-':
possible.append((index_col,index_row))
if len(possible) == 0:
# we cant place an apple
return False
else:
(col,row) = random.choice(possible)
world[row][col] = APPLE_SYMBOL
return True
world = empty()
player_row = 0
player_col = 0
player_history = []
world[player_row][player_col] = '%'
player_history.append((player_col,player_row))
place_apple(world)
render(world)
while True:
direction = input("which direction: ")
world[player_row][player_col] = '='
if direction == "u":
player_row = player_row - 1
elif direction == "d":
player_row = player_row + 1
elif direction == "l":
player_col = player_col - 1
elif direction == "r":
player_col = player_col + 1
else:
print("try again, u for up/d for down/l for left/r for right")
continue
if snake_eats_itself(player_history, player_col, player_row):
print("GAME OVER")
break
if world[player_row][player_col] == APPLE_SYMBOL:
world[player_row][player_col] = '$'
if not place_apple(world):
print("YOU WON!")
break
else:
world[player_row][player_col] = '%'
player_history.append((player_col,player_row))
render(world)
```
[DAY-58] Continue Previous Day
Keep working on the snake game if you are not done. if you are do touch typing
[DAY-59] Tuples; Lists
Tuples are kind of like lists that you cant grow or shrink, but also you usually assign meaning to each of the positions, for example
```
position = (1,2)
(x,y) = position
print(x)
print(y)
```
it can have more elements
```
posittion = (1,2,3)
(width,depth,height) = position
print(width)
print(depth)
print(height)
```
You see how we used it in the snake game, to make a list of tuples, where we had the player history.
positions = [(1,2),(3,4),(5,6)]
print(positions)
for p in positions:
print(p)
(x,y) = p
print(x)
print(y)
It is quite handy when you know you have pairs of data, like X and Y position or Season number and Episode number.
```
favorite_miraculous = [(3,1),(3,2),(2,1)]
for m in favorite_miraculous:
(season,episode) = m
print(str(season) + " season episode: " + str(episode))
```
Or more than 2 pieces, you can hold however many you want, but it usually is you that assign meaning to each position, like in the above case, the first element we decide is season, and the second one we decide is episode
[DAY-60] Go Back In Time
Back to the beginning.
Write a program to make a spy name
Write a program to ask for favorite food
Write a program to ask what is your name forever
[DAY-61] PyGame; PyGameZero; Coordinates
open cmd
and run:
pip install pygame
pip install pgzero
then make a circle
```
import pgzrun
WIDTH = 400
HEIGHT = 400
def draw():
screen.clear()
x = WIDTH/2
y = WIDTH/2
pos = (x,y)
radius = 30
screen.draw.circle(pos, radius, 'white')
pgzrun.go()
```
Now lets move it:
```
import pgzrun
import random
WIDTH = 400
HEIGHT = 400
x = WIDTH/2
y = WIDTH/2
def on_mouse_down(pos):
global x,y
(mouse_x, mouse_y) = pos
x = mouse_x
y = mouse_y
def draw():
screen.clear()
pos = (x,y)
radius = 30
screen.draw.circle(pos, radius, 'white')
pgzrun.go()
```
Move it with keyboard
```
import pgzrun
import random
WIDTH = 400
HEIGHT = 400
STEP = 10
x = WIDTH/2
y = WIDTH/2
def on_key_down(key):
global x,y
if key == keys.LEFT:
x -= STEP
elif key == keys.RIGHT:
x += STEP
elif key == keys.UP:
# coordinates start 0,0 on the upper left corner
y -= STEP
elif key == keys.DOWN:
y += STEP
def draw():
screen.clear()
pos = (x,y)
radius = 30
screen.draw.circle(pos, radius, 'white')
pgzrun.go()
```
Lets say we have 400 width and 300 height window
(0,0)
+---------------------------+
| |
| |
| |
| |
| |
| |
+---------------------------+
(400, 300)
top left corner is y = 0 and x = 0, bottom right is x = 400
and y = 300
. So when we move 'UP' with the keyboard we actually have to decrease y
instead of increasing it like in turtle
, where 0,0 is in the center of the screen, so top left is (-half_x, -half_y)
and bottom right is (half_x, half_y)
[DAY-62] Collisions; Callbacks
Smooth movement.
```
import pgzrun
import random
WIDTH = 400
HEIGHT = 400
STEP = 10
x = WIDTH/2
y = WIDTH/2
def update():
global x,y
if keyboard.LEFT:
x -= STEP
elif keyboard.RIGHT:
x += STEP
elif keyboard.UP:
y -= STEP
elif keyboard.DOWN:
y += STEP
def draw():
screen.clear()
pos = (x,y)
radius = 30
screen.draw.circle(pos, radius, 'white')
pgzrun.go()
```
pgzero
will call your update
function 60 times per second, and now it will just check at the time of the call, is keyboard.UP
, and if it is it will just move. Which is completely different, where each time you press the up
key the on_key_down
function is called. So previously you had ot press the key every time to move, now you can just hold it.
Where do those keyboard
and screen
magic variables come from? In python there is such thing as __builtin__
which literally adds new keywords, kind of like input
or print
, when you import pgzrun
it will import also those builtins. Actor
, Rect
, keyboard
etc.. you can check them at https://pygame-zero.readthedocs.io/en/stable/builtins.html
COLLIDE!
```
import pgzrun
import random
WIDTH = 400
HEIGHT = 400
STEP = 10
x = WIDTH/2
y = WIDTH/2
box = Rect((20,20),(100,100))
game_over = False
def update():
global x, y, game_over
if keyboard.LEFT:
x -= STEP
elif keyboard.RIGHT:
x += STEP
elif keyboard.UP:
y -= STEP
elif keyboard.DOWN:
y += STEP
if box.collidepoint((x,y)):
game_over = True
def draw():
screen.clear()
pos = (x,y)
radius = 30
screen.draw.rect(box, color="red")
screen.draw.circle(pos, radius, 'white')
if game_over:
screen.draw.text("GAME OVER", (50, 30), color="blue")
pgzrun.go()
```
[DAY-63] Functions
Catch the snake
Make images/ folder and download the images from https://github.com/jackdoe/programming-for-kids. When you say Actor("c1")
it will look for c1.png
in images/ folder in the current directory.
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
score = 0
speed = 1
elf = Actor("c1")
snake = Actor("snake")
elf.x = WIDTH/2
elf.y = HEIGHT/2
def place_snake():
snake.x = random.randint(10,WIDTH-10)
snake.y = random.randint(10,HEIGHT-10)
place_snake()
def update():
global game_over, speed, score
if keyboard.left:
elf.x = elf.x-speed
if keyboard.right:
elf.x = elf.x+speed
if keyboard.up:
elf.y = elf.y-speed
if keyboard.down:
elf.y= elf.y+speed
if keyboard.R:
speed = 1
score = 0
if elf.colliderect(snake):
score += 1
speed += 1
place_snake()
def draw():
screen.fill('black')
elf.draw()
snake.draw()
screen.draw.text("Score: "+ str(score), color="white", topleft=(10,10))
pgzrun.go()
```
[DAY-64] Lists; Functions
Many Snakes
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
score = 1
speed = 1
elf = Actor("c1")
snakes = []
elf.x = WIDTH/2
elf.y = HEIGHT/2
def place_snakes():
global snakes
snakes = []
for i in range(score):
snake = Actor("snake")
snake.x = random.randint(10,WIDTH-10)
snake.y = random.randint(10,HEIGHT-10)
snakes.append(snake)
place_snakes()
def update():
global game_over, speed, score, snakes
if keyboard.left:
elf.x = elf.x-speed
if keyboard.right:
elf.x = elf.x+speed
if keyboard.up:
elf.y = elf.y-speed
if keyboard.down:
elf.y= elf.y+speed
if keyboard.R:
speed = 1
score = 0
snakes = []
place_snakes()
for s in snakes:
if elf.colliderect(s):
score += 1
speed += 1
place_snakes()
def draw():
screen.fill('black')
elf.draw()
for s in snakes:
s.draw()
screen.draw.text("Score: "+ str(score), color="white", topleft=(10,10))
pgzrun.go()
```
[DAY-65] Functions; Collisions
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
score = 0
speed = 1
game_over = False
elf = Actor("c1")
snake = Actor("snake")
elf.x = WIDTH/2
elf.y = HEIGHT/2
def place_snake():
snake.x = random.randint(10,WIDTH-10)
snake.y = random.randint(10,HEIGHT-10)
place_snake()
def update():
global game_over, speed, score
if keyboard.left:
elf.x = elf.x-speed
if keyboard.right:
elf.x = elf.x+speed
if keyboard.up:
elf.y = elf.y-speed
if keyboard.down:
elf.y= elf.y+speed
if keyboard.R:
speed = 1
score = 0
if elf.colliderect(snake):
score += 1
speed += 1
place_snake()
def draw():
screen.fill('black')
elf.draw()
snake.draw()
screen.draw.text("Score: "+ str(score), color="white", topleft=(10,10))
pgzrun.go()
```
[DAY-66] Schedule; Callbacks; Functions
Catch as many snakes as you can in 5 seconds.
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
game_over = False
score = 0
speed = 1
elf = Actor("c1")
snake = Actor("snake")
elf.x = WIDTH/2
elf.y = HEIGHT/2
def place_snake():
snake.x = random.randint(10,WIDTH-10)
snake.y = random.randint(10,HEIGHT-10)
place_snake()
def time_is_up():
global game_over
game_over = True
def update():
global game_over, speed, score
if keyboard.left:
elf.x = elf.x-speed
if keyboard.right:
elf.x = elf.x+speed
if keyboard.up:
elf.y = elf.y-speed
if keyboard.down:
elf.y= elf.y+speed
if keyboard.R:
speed = 1
score = 0
if elf.colliderect(snake):
score += 1
speed += 1
place_snake()
def draw():
screen.fill('black')
elf.draw()
snake.draw()
screen.draw.text("Score: "+ str(score), color="white", topleft=(10,10))
if game_over:
screen.fill('blue')
screen.draw.text("GAME OVER, Score: "+ str(score), color="white", topleft=(10,10))
clock.schedule(time_is_up, 5)
pgzrun.go()
```
You see we just overwrite the screen with 'blue' and write another text, but you can still move in the back and the score will update if you catch a sneak.
If you want to stop the hero to move outside of the window, simply restrict elf.x and elf.y to be smaller than 0 or bigger than WIDTH and HEIGHT
Example:
```
def update():
...
if keyboard.left:
elf.x = elf.x-speed
if elf.x > WIDTH:
elf.x = WIDTH
```
[DAY-67] Lists; Functions
Cross the road. Work with your parent to find images for the game, you need few cars, fox and a door. If not just use the existing assets from your images/ folder
```
import pgzrun
import random
HEIGHT = 1000
WIDTH = 1200
score = 0
step = 5
coin_speed = 1
fox = Actor("fox")
gate = Actor("door")
gate.y = HEIGHT - 50
gate.x = WIDTH/2 - 20
cars=[
[Actor("car-2"),Actor("car-5"),Actor("car-3")],
[Actor("car-1"),Actor("car-5")],
[Actor("car-3"),Actor("car-4"),Actor("car-2")],
]
for a in cars:
for (coin_index,f) in enumerate(a):
f.x += coin_index * int(WIDTH/len(a)) + 30
def move_coins():
for (index,a) in enumerate(cars):
for (coin_index, f) in enumerate(a):
f.y = (index * int(HEIGHT/len(cars))) + int(HEIGHT/len(cars))/2
f.x += coin_speed
if f.x > WIDTH:
f.x = 0
game_over = False
move_coins()
def update():
global score
global step
global game_over
global coin_speed
if keyboard.left:
fox.x = fox.x-step
if fox.x <0:
fox.x=0
if keyboard.right:
fox.x = fox.x+step
if fox.x >WIDTH:
fox.x=WIDTH
if keyboard.up:
fox.y =fox.y-step
if fox.y <0:
fox.y=0
if keyboard.down:
fox.y= fox.y+step
if fox.y >HEIGHT:
fox.y=HEIGHT
if keyboard.R:
game_over = False
score = 0
fox.x = 0
fox.y = 0
coin_speed = 1
for i in cars:
for s in i:
if fox.colliderect(s):
game_over = 1 == 1
if fox.colliderect(gate):
fox.x = 0
fox.y = 0
score += 1
coin_speed += 2
move_coins()
def draw():
screen.fill('black')
fox.draw()
gate.draw()
for i in cars:
for k in i:
k.draw()
screen.draw.text("Score: "+ str(score), color="white", topleft=(10,10))
if game_over:
screen.fill("blue")
screen.draw.text("Final Score: "+ str(score), color="white", topleft=(10,10),fontsize=60)
pgzrun.go()
```
[DAY-68] Lists; Functions
Shoot bullets and remove them from the list, play sound, and also level up after killing 3 snakes!
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
score = 0
speed = 1
elf = Actor("c1")
snake = Actor("snake")
beep = tone.create('A3', 0.5)
elf.x = WIDTH/2
elf.y = HEIGHT/2
bullets = []
def place_snake():
snake.x = random.randint(10,WIDTH-10)
snake.y = random.randint(10,HEIGHT-10)
place_snake()
def bullet_out_of_screen():
# just delete the first bullet
bullets.pop(0)
def on_key_down(key):
if key == keys.SPACE:
b = Actor("bullet2")
b.x = elf.x + 5
b.y = elf.y
animate(b, pos=(WIDTH + 100, elf.y), tween='accelerate', on_finished=bullet_out_of_screen)
bullets.append(b)
def update():
global game_over, speed, score, bullets
if keyboard.left:
elf.x = elf.x-speed
if keyboard.right:
elf.x = elf.x+speed
if keyboard.up:
elf.y = elf.y-speed
if keyboard.down:
elf.y= elf.y+speed
if keyboard.R:
speed = 1
score = 0
elf.image = "c1"
bullets = []
for b in bullets:
if b.colliderect(snake):
score += 1
speed += 1
if score == 3:
elf.image = "c2"
beep.play()
place_snake()
def draw():
screen.fill('black')
elf.draw()
snake.draw()
for b in bullets:
b.draw()
screen.draw.text("Score: "+ str(score), color="white", topleft=(10,10))
pgzrun.go()
```
You see how we are adding, bullets to a list every time you press 'space'. Now the problem is we need to clean up that list at some point, otherwise it will grow a lot, and every time we do for b in bullets
it will bet slower and slower. Computers can only do so many things per second.
So when the animation finishes, it will call bullets_out_of_screen
, and from there we just say bullets.pop(0)
which will remove the first element in the list of bullets, which is the oldest bullet. So if you press space 5 times, the list will have 5 items, and each of them will finish and will remove the first element.
Lets say you pressed space 3 times, and shot 3 bullets, so the list, and how the bullets are traveling kindof looks like this:
0 -> bbbbbbbbbbbbbb
1 -> bbbbbbb
2 -> bbbb
So you see when 0 finishes because it is the oldest, when it does bullets.pop(0), it will actually delete itself.
pretty cool!
[DAY-69] Sockets; Functions; Callbacks
Multiplayer!
```
import pgzrun
import socket
import threading
import sys
HEIGHT = 200
WIDTH = 200
MULTIPLAYER_PORT = 5025
OTHER_COMPUTER_IP = "192.168.0.10"
speed = 4
me = Actor("c1")
other = Actor("c2")
me.x = WIDTH/2
me.y = HEIGHT/2
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket.bind(("0.0.0.0", MULTIPLAYER_PORT))
data = None
def multiplayer():
global data
while True:
data, addr = socket.recvfrom(1024)
def update():
if data != None:
message = data.decode("utf8")
(x,y) = message.split(":")
other.x = float(x)
other.y = float(y)
def on_key_down(key):
if key == keys.LEFT:
me.x = me.x-speed
if key == keys.RIGHT:
me.x = me.x+speed
if key == keys.UP:
me.y = me.y-speed
if key == keys.DOWN:
me.y= me.y+speed
if key == keys.Q:
sys.exit(0)
message = bytearray(str(me.x) + ':' + str(me.y),"utf8")
socket.sendto(message, (OTHER_COMPUTER_IP, MULTIPLAYER_PORT))
def draw():
screen.fill('black')
me.draw()
other.draw()
threading.Thread(target=multiplayer).start()
pgzrun.go()
```
There are two important parts here, first is the socket
and then the Thread
. For now we will leave them a mystery. But basically every time you press the UP/DOWN/LEFT/RIGHT key your computer sends a message "currentX:currentY" to the other computer, and when the other computer receives it, it stores it in the global data
variable, then in the update
function it splits the message by :
and extract the x
and y
and sets it to the other
actor.
The multiplayer()
function runs in a separate thread, or you can think of a separate process, so we are doing two things in the same time, the game loop (which is one while True
) and the multiplayer loop which is also while True
.
[DAY-70] Lists; Functions
print numbers in a list
data = [1,2,3,4,5]
for item in data:
print(e)
list_of_lists = [[1,2,3,4,5], [1,2,3], [4,5,6]]
for l in list_of_lists:
for item in l:
print(item)
list_of_list_of_lists = [[[1,2,3,4,5], [1,2,3], [4,5,6]], [[1,2,3,4,5], [1,2,3], [4,5,6]]]
for list_of_lists in list_of_list_of_lists:
for l in list_of_lists:
for item in l:
print(item)
```
list_of_list_of_list_of_lists = [
[
[
[1,2,3,4,5],
[1,2,3],
[4,5,6]
],
[
[1,2,3,4,5],
[1,2,3],
[4,5,6]
]
],
[
[
[1,2,3,4,5],
[1,2,3],
[4,5,6]
],
[
[1,2,3,4,5],
[1,2,3],
[4,5,6]
]
],
]
for list_of_list_of_lists in list_of_list_of_list_of_lists:
for list_of_lists in list_of_list_of_lists:
for l in list_of_lists:
for item in l:
print(item)
```
```
def sum(x):
r = 0
for item in x:
r += item
return r
data = [1,2,3,4,5]
print(sum(data))
```
```
def sum(x):
r = 0
for l in x:
for item in l:
r += item
return r
data = [[1,2,3,4,5], [1,2,3,4,5]]
print(sum(data))
```
[DAY-71] Strings; Integers; While; Functions
make a calculator
```
while True:
n1 = int(input("number 1: "))
n2 = int(input("number 2: "))
op = input("operation +/-* : ")
r = 0
if op == "quit":
break
elif op == "+":
r = n1 + n2
elif op == "-":
r = n1 - n2
elif op == "*":
r = n1 * n2
else:
print("i dont know " + op)
continue
print(n1, op, n2, '=',r)
```
sum numbers from input
```
def sum(x):
r = 0
for item in x:
r += item
return r
x = []
while True:
k = input("enter number: ")
x.append(int(k))
print(x)
print(sum(x))
```
[DAY-72] Reading Code
Reading code is even more important than writing it, and it is more difficult than reading a book, because the story does not develop top to bottom. You have to see the important pieces, and how they are linked together. Where are things assigned and changed and how are those pieces related. For example in the touch typing program, you have a couple of functions, you can study them on their own, and know what they do, and then see how they are used and make sense of the whole program, without even running it.
We will go over a couple of programs we wrote before, the rock paper scissors game, the bullet shooting game, and one of the touch typing programs.
Those are just examples, you have to print the programs and go over them with your parent.
[DAY-73] Reading Code
More reading today, those are a couple of examples from the earlier days, the love tester, the fight function from the text game, the hangman game and first touch typing program.
Again you can use something else as well, those are just the ones I picked. Be messy with the pencil, connect things together!
[DAY-74] Strings; While; Lists
Today its up to you what to write, my kid came up with those programs:
Ask forever what your favorite sport is, if yours is not here use https://emojipedia.org/ to find good emojis.
```
while True:
k = input('what is your favorite sport: ')
if k == 'soccer':
print('⚽')
elif k == 'hockey':
print('🏑')
elif k == 'tennis':
print('🎾')
elif k == 'volleyball':
print('🏐')
elif k == 'table tennis':
print('🏓')
elif k == 'baseball':
print('⚾')
elif k == 'basketball':
print('🏀')
elif k == 'golf':
print('🏌️♂️')
else:
print('i dont now ' +k)
```
and one simple, append and pop from a list.
k = []
while True:
s = input('What are you thinking of: ')
if s == 'pop':
k.pop(0)
else:
k.append(s)
print(k)
[DAY-75] Functions; Callbacks; Lists; Encoding
Enemies come to get you, and you shoot half moons at them. pretty cool.
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
score = 0
speed = 1
elf = Actor("c1")
beep = tone.create('A3', 0.5)
elf.x = 10
elf.y = HEIGHT/2
game_over = False
bullets = []
enemies = []
def make_enemies():
level = int(score / 5) + 1
duration = (5 - level)
if duration < 1:
duration = 1
for i in range(level):
snake = Actor("snake")
snake.x = WIDTH-20
snake.y = random.randint(10,HEIGHT-10)
animate(snake, pos=(-100, snake.y), tween='accelerate', duration=duration)
enemies.append(snake)
def bullet_out_of_screen():
bullets.pop(0)
def on_key_down(key):
if key == keys.SPACE:
b = Actor("bullet2")
b.x = elf.x + 5
b.y = elf.y
animate(b, pos=(WIDTH + 100, elf.y), tween='accelerate', on_finished=bullet_out_of_screen)
bullets.append(b)
def update():
global game_over, speed, score, bullets, enemies
if keyboard.left:
elf.x = elf.x-speed
if keyboard.right:
elf.x = elf.x+speed
if keyboard.up:
elf.y = elf.y-speed
if keyboard.down:
elf.y= elf.y+speed
if keyboard.R:
speed = 1
score = 0
bullets = []
enemies = []
game_over = False
hit = []
for b in bullets:
for e in enemies:
if b.colliderect(e):
hit.append(e)
if len(hit) > 0:
score += len(hit)
if speed < 4:
speed += 1
beep.play()
for e in hit:
enemies.remove(e)
for e in enemies:
if e.colliderect(elf):
game_over = True
def draw():
if game_over:
screen.fill('black')
screen.draw.text("GAME OVER", color="white", topleft=(10,10))
else:
screen.fill('black')
elf.draw()
for b in bullets:
b.draw()
for e in enemies:
e.draw()
screen.draw.text("Score: "+ str(score), color="white", topleft=(10,10))
make_enemies()
clock.schedule_interval(make_enemies, 2)
pgzrun.go()
```
tic tac toe but with one character variable names
```
x = [
# 0 1 2 3
['〰️','🅰️','🅱️','🅾️'], # 0
['🥇','〰️','〰️','〰️'], # 1
['🥈','〰️','〰️','〰️'], # 2
['🥉','〰️','〰️','〰️'], # 3
]
k = '🛹'
while True:
for i in x:
for s in i:
print(s,end=' ')
print('')
l = input(k + ": ")
if l == 'a1':
x[1][1]=k
elif l == 'a2':
x[2][1]=k
elif l == 'a3':
x[3][1]=k
elif l == 'b1':
x[1][2]=k
elif l == 'b2':
x[2][2]=k
elif l == 'b3':
x[3][2]=k
elif l == 'o1':
x[1][3]=k
elif l == 'o2':
x[2][3]=k
elif l == 'o3':
x[3][3]=k
else:
continue
if k == '🛹':
k = '⚽'
else:
k = '🛹'
```
30 and back
for i in range(1,31):
print(i)
for i in range(1,31):
print(30 - i)
football mania
d = 30
while True:
for i in range(1,d):
print('⚽' * i)
for i in range(1,d):
h = (d - i)
print('⚽' * h)
[DAY-76] Functions; Callbacks; Lists
A game of tag! The elf is robin hood, running away from the king. The elf plays with WASD and the king plays with up/down/left/right.
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
speedA = 3
speedB = 3
playerA = Actor("c1")
playerB = Actor("c2")
playerA.x = 10
playerA.y = HEIGHT - 40
playerB.x = 10
playerB.y = 40
game_over = False
def random_speed():
global speedA, speedB
speedA = random.randint(1,5)
speedB = random.randint(1,5)
def on_key_down(key):
global game_over
# player A
if key == keys.A:
playerA.x -= speedA
if key == keys.D:
playerA.x += speedA
if key == keys.W:
playerA.y -= speedA
if key == keys.S:
playerA.y += speedA
# player B
if key == keys.LEFT:
playerB.x -= speedB
if key == keys.RIGHT:
playerB.x += speedB
if key == keys.UP:
playerB.y -= speedB
if key == keys.DOWN:
playerB.y += speedB
def update():
global game_over
if playerA.colliderect(playerB):
game_over = True
def draw():
if game_over:
screen.fill('black')
screen.draw.text("GAME OVER", color="white", topleft=(10,10))
else:
screen.fill('black')
screen.draw.text("RUN! elf: " + str(speedA) + " king: " + str(speedB) , color="white", topleft=(10,10))
playerA.draw()
playerB.draw()
clock.schedule_interval(random_speed, 2)
pgzrun.go()
```
Basic math quiz
import random
while True:
k = random.randint(1,13)
s = random.randint(1,13)
r = k * s
g = int(input('How much is '+str(k) +'*' +str(s) + ': '))
if g == r:
print('Wow nice job its CORRECT')
else:
print('wrong the answer was: ' + str(r))
7 days average
```
x = [1231,5123,6737,6725,6261,2664,62561]
n = len(x)
print(x)
print(n)
sum = 0
for i in x:
sum += i
print('sum: ' + str(sum))
print('average: ' + str(sum/n))
```
[DAY-77] Lists; Encode/Decode
morse code translator
```
alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' ','.',',']
morse = ['.-','-...','-.-.','-..','.','..-.','--.','....','..','.---','-.-','.-..','--','-.','---','.--.','--.-','.-.','...','-','..-','...-','.--','-..-','-.--','--..','/','.-.-.-','--..--']
print(len(morse))
print(len(alphabet))
for i in range(len(alphabet)):
print(alphabet[i] + " -> " + morse[i])
text = '.... . .-.. .-.. --- / .-- --- .-. .-.. -.. .-.-.- / - .... .. ... / .. ... / -- --- .-. ... . / -.-. --- -.. . .-.-.- / - .... . .-. . / .- .-. . / -- .- -. -.-- / -.-. --- -.. . ... --..-- / -... ..- - / - .... .. ... / --- -. . / .. ... / .--. .-. . - - -.-- / -.-. --- --- .-.. --..-- / --. --- --- -.. / .--- --- -... / - .-. .- -. ... .-.. .- - .. -. --. / .. - .-.-.-'.split(' ')
for word in text:
found = False
for i in range(len(morse)):
x = morse[i]
if x == word:
print(alphabet[i], end = '')
found = True
if not found:
print(word , end='')
```
[DAY-78] Coordinates; Functions; Callbacks
Small modifications to the previous game, gold in the middle moves the king away, randomize the elf position every 2 seconds
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
speedE = 3
speedK = 3
elf = Actor("c1")
king = Actor("c2")
gold = Actor("c3")
gold.x = WIDTH/2
gold.y = HEIGHT/2
elf.x = 10
elf.y = HEIGHT - 40
king.x = 10
king.y = 40
game_over = False
def random_speed():
global speedE, speedK
speedE = random.randint(3,5)
speedK = random.randint(2,5)
def random_place():
elf.x = random.randint(0,WIDTH)
elf.y = random.randint(0,HEIGHT)
def update():
global game_over
# elf
if keyboard.A:
elf.x -= speedE
if keyboard.D:
elf.x += speedE
if keyboard.W:
elf.y -= speedE
if keyboard.S:
elf.y += speedE
# king
if keyboard.left:
king.x -= speedK
if keyboard.right:
king.x += speedK
if keyboard.up:
king.y -= speedK
if keyboard.down:
king.y += speedK
if keyboard.SPACE:
elf.image = 'snake'
random_speed()
if keyboard.R:
game_over = 1==2
elf.x = 10
elf.y = HEIGHT - 40
king.x = 10
king.y = 40
if elf.x < 0:
elf.x = 0
if elf.x > WIDTH:
elf.x = WIDTH
if elf.y < 0:
elf.y = 0
if elf.y > HEIGHT:
elf.y = HEIGHT
if king.x < 0:
king.x = 0
if king.x > WIDTH:
king.x = WIDTH
if king.y < 0:
king.y = 0
if king.y > HEIGHT:
king.y = HEIGHT
if elf.colliderect(gold):
king.x = WIDTH
king.y = HEIGHT
if king.colliderect(gold):
game_over = True
if elf.colliderect(king):
game_over = True
def draw():
if game_over:
screen.fill('black')
screen.draw.text("GAME OVER", color="white", topleft=(10,10))
else:
screen.fill('black')
screen.draw.text("RUN! elf: " + str(speedE) + " king: " + str(speedK) , color="white", topleft=(10,10))
elf.draw()
king.draw()
gold.draw()
clock.schedule_interval(random_speed, 2)
clock.schedule_interval(random_place, 5)
pgzrun.go()
```
Explanation about setting x and y to be random:
Write a program to compute the average of a list of numbers:
Decode morse code:
[DAY-79] Lists; Encoding
morse code agian
```
alphabet = ['a','b','c','d','e']
morse = ['.-','-...','-.-.','...','.']
for i in range(len(alphabet)):
print(alphabet[i])
print(morse[i])
text = ['.-..','.','.-..','.-']
for word in text:
for c in range(len(morse)):
if word == morse[c]:
print(alphabet[c])
```
[DAY-80] Lists; Functions
PONG (almost)
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
left = Actor("c1")
left.x = 10
left.y = HEIGHT/2
right = Actor("c2")
right.x = WIDTH - 10
right.y = HEIGHT/2
ball = Actor("bullet")
ball.x = WIDTH/2
ball.y = HEIGHT/2
game_area = Rect((0, 0), (WIDTH, HEIGHT))
game_over = False
def send_ball_to(direction):
duration = 3
if direction == 'left':
animate(ball, pos=(-100, random.randint(0,HEIGHT)), tween='linear', duration=duration)
else:
animate(ball, pos=(WIDTH + 100, random.randint(0,HEIGHT)), tween='linear', duration=duration)
def update():
global game_over
speed = 3
if keyboard.R:
ball.x = WIDTH/2
ball.y = HEIGHT/2
send_ball_to('left')
game_over = False
if keyboard.W:
left.y -= speed
if keyboard.S:
left.y += speed
if keyboard.up:
right.y -= speed
if keyboard.down:
right.y += speed
if left.colliderect(ball):
send_ball_to('right')
if right.colliderect(ball):
send_ball_to('left')
if not ball.colliderect(game_area):
game_over = True
def draw():
if game_over:
screen.fill('black')
screen.draw.text("GAME OVER", color="white", topleft=(10,10))
else:
screen.fill('black')
left.draw()
right.draw()
ball.draw()
screen.draw.rect(game_area, (200, 0, 0))
send_ball_to('left')
pgzrun.go()
```
average of two lists
[DAY-81] Lists; Encoding
First image
+-----+
| * * |
| * |
| * * |
+-----+
list of lists with pixels
```
image = [
[1,3,3,3,3,3,1],
[2,4,5,4,5,4,2],
[2,4,4,5,4,4,2],
[2,4,5,4,5,4,2],
[1,3,3,3,3,3,1],
]
for row in image:
for pixel in row:
if pixel == 1:
print('+', end='')
elif pixel == 2:
print('|', end='')
elif pixel == 3:
print('-', end='')
elif pixel == 4:
print(' ', end='')
elif pixel == 5:
print('*', end='')
else:
print("dont know what to do with: " + str(pixel))
print('')
```
just a list of pixels
```
image = [
1,3,3,3,3,3,1,
2,4,5,4,5,4,2,
2,4,4,5,4,4,2,
2,4,5,4,5,4,2,
1,3,3,3,3,3,1,
]
width = 7
for (index, pixel) in enumerate(image):
if index > 0 and index % width == 0:
print('')
if pixel == 1:
print('+', end='')
elif pixel == 2:
print('|', end='')
elif pixel == 3:
print('-', end='')
elif pixel == 4:
print(' ', end='')
elif pixel == 5:
print('*', end='')
else:
print("dont know what to do with: " + str(pixel))
```
some fun with lists
```
x = ['a','b','c','d']
m = ['w','x','y','z']
d = ['g','h','j','k']
a -> 0
b -> 1
c -> 2
for i in range(len(x)):
print(i,end=' ')
print(x[i],end=' ')
print(m[i],end=' ')
print(d[i])
```
how similar are lists and strings
```
x = 'hello'
for i in range(len(x)):
print(i,end=' ')
print(x[i])
```
similar, but not quite, you cant change the inside of a string, but you can change the inside of a list.
```
x = ['h','e','l','l','o']
y = 'hello'
x[2] = 'm'
y = 'hemlo'
for i in range(len(x)):
print(i,end=' ')
print(x[i], end=' ')
print(y[i])
```
sum many lists
```
a = [6,3,2]
b = [78,21,1]
c = [123,5,1]
sum = 0
for i in range(len(a)):
sum += a[i] + b[i] + c[i]
print(sum)
```
another way to sum
```
a = [6,3,2]
b = [78,21,1]
c = [123,5,1]
sum = 0
for x in a:
sum += x
for x in b:
sum += x
for x in c:
sum += x
print(sum)
```
[DAY-82] Lists; Strings
simple game with history, press S to save your position to a list of positions, and then B to go back in time
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
player = Actor("c1")
player.x = WIDTH/2
player.y = HEIGHT/2
history = []
def on_key_down(key):
speed = 3
if key == keys.UP:
player.y -= speed
if key == keys.DOWN:
player.y += speed
if key == keys.LEFT:
player.x -= speed
if key == keys.RIGHT:
player.x += speed
if key == keys.S:
position = [player.x, player.y]
history.append(position)
print('append', history)
if key == keys.B and len(history) > 0:
last = history.pop()
player.x = last[0]
player.y = last[1]
print('pop', history)
def draw():
screen.fill('black')
player.draw()
pgzrun.go()
```
Two players, and more positions
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
player1 = Actor("c1")
player2 = Actor('c2')
history = []
def on_key_down(key):
speed = 10
if key == keys.W:
player1.y-= speed
if key == keys.A:
player1.x-=speed
if key == keys.S:
player1.y += speed
if key == keys.D:
player1.x += speed
if key == keys.UP:
player2.y-= speed
if key == keys.LEFT:
player2.x-=speed
if key == keys.DOWN:
player2.y += speed
if key == keys.RIGHT:
player2.x += speed
if key == keys.F:
positions = [player1.x,player1.y,player2.x,player2.y]
history.append(positions)
print('push', history)
if key == keys.G:
if len(history) > 0:
positions = history.pop()
player1.x = positions[0]
player1.y = positions[1]
player2.x = positions[2]
player2.y = positions[3]
print('pop', history)
def draw():
screen.fill('black')
player1.draw()
player2.draw()
pgzrun.go()
```
More lists
```
a = ['h','w','e']
b = ['e','o','a']
c = ['l','r','r']
d = ['l','l','t']
e = ['o','d','h']
sum1 = ''
sum2 = ''
sum1 = a[0] + b[0] + c[0] + d[0] + e[0]
sum2 = a[1] + b[1] + c[1] + d[1] + e[1]
print(sum1)
print(sum2)
sum = []
for i in range(len(a)):
sum.append('')
sum[i] = a[i] + b[i] + c[i] + d[i] + e[i]
print(sum)
```
sum from the input
```
list = []
while True:
integer = int(input('enter a number: '))
list.append(integer)
sum = 0
for i in list:
sum += i
print(list, sum)
```
[DAY-83] Lists; Functions
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
player = Actor("c1")
player.x = WIDTH/2
player.y = HEIGHT/2
things = []
def on_key_down(key):
speed = 10
if key == keys.UP:
player.y -= speed
if key == keys.DOWN:
player.y += speed
if key == keys.LEFT:
player.x -= speed
if key == keys.RIGHT:
player.x += speed
if key == keys.F:
thing = Actor("flower")
thing.x = player.x
thing.y = player.y
things.append(thing)
if key == keys.R:
thing = Actor("rock")
thing.x = player.x
thing.y = player.y
things.append(thing)
def draw():
screen.fill('black')
player.draw()
for t in things:
t.draw()
pgzrun.go()
```
With a function, so we can add more keys faster and we dont duplicate that much code
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
player = Actor("c1")
player.x = WIDTH/2
player.y = HEIGHT/2
things = []
def place_thing(kind):
thing = Actor(kind)
thing.x = player.x
thing.y = player.y
things.append(thing)
def on_key_down(key):
speed = 15
if key == keys.UP:
player.y -= speed
if key == keys.DOWN:
player.y += speed
if key == keys.LEFT:
player.x -= speed
if key == keys.RIGHT:
player.x += speed
if key == keys.F:
place_thing("flower")
if key == keys.R:
place_thing("rock")
if key == keys.K:
place_thing("c2")
def draw():
screen.fill('black')
player.draw()
for t in things:
t.draw()
pgzrun.go()
```
Now we can make a map, just add the kind of thing, its x and y position in a list and print it, after we are done building the map we can use it later
```
...
game_map = []
def place_thing(kind):
thing = Actor(kind)
thing.x = player.x
thing.y = player.y
things.append(thing)
game_map.append([kind, thing.x, thing.y])
print(game_map)
...
```
use the map:
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
player = Actor("c1")
player.x = WIDTH/2
player.y = HEIGHT/2
things = []
def place_thing(kind,x,y):
thing = Actor(kind)
thing.x = x
thing.y = y
things.append(thing)
def on_key_down(key):
speed = 15
if key == keys.UP:
player.y -= speed
if key == keys.DOWN:
player.y += speed
if key == keys.LEFT:
player.x -= speed
if key == keys.RIGHT:
player.x += speed
def draw():
screen.fill('black')
player.draw()
for t in things:
t.draw()
game_map = [['rock', 100.0, 55.0], ['flower', 100.0, 85.0], ['c2', 100.0, 130.0], ['c2', 70.0, 130.0], ['c2', 55.0, 130.0], ['c2', 40.0, 130.0], ['c2', 25.0, 130.0], ['c2', 25.0, 100.0], ['c2', 25.0, 85.0], ['c2', 25.0, 70.0], ['c2', 25.0, 55.0], ['c2', 25.0, 40.0], ['c2', 25.0, 25.0], ['c2', 40.0, 25.0], ['c2', 55.0, 25.0], ['c2', 70.0, 25.0], ['c2', 85.0, 25.0], ['c2', 100.0, 25.0], ['c2', 115.0, 25.0], ['c2', 130.0, 25.0], ['c2', 145.0, 25.0], ['c2', 145.0, 40.0], ['c2', 145.0, 55.0], ['c2', 145.0, 70.0], ['c2', 145.0, 85.0], ['c2', 145.0, 100.0], ['c2', 145.0, 115.0], ['c2', 145.0, 130.0], ['c2', 130.0, 130.0], ['c2', 115.0, 130.0], ['c2', 100.0, 130.0], ['c2', 85.0, 130.0], ['c2', 25.0, 115.0]]
for g in game_map:
place_thing(g[0],g[1],g[2])
pgzrun.go()
```
Another way to do it, press S to print the list of things, and then paste it in the game[] list to use it, D deletes things where you stand, and U removes the last thing
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
player = Actor("c1")
things = []
game = []
for g in game:
t = Actor(g[0])
t.x = g[1]
t.y = g[2]
things.append(t)
def on_key_down(key):
speed = 10
if key == keys.UP:
player.y -= speed
if key == keys.DOWN:
player.y += speed
if key == keys.LEFT:
player.x -= speed
if key == keys.RIGHT:
player.x += speed
if key == keys.F:
f = Actor("flower")
f.x = player.x
f.y = player.y
things.append(f)
if key == keys.R:
f = Actor("rock")
f.x = player.x
f.y = player.y
things.append(f)
if key == keys.U:
things.pop()
if key == keys.D:
collide = []
for t in things:
if player.colliderect(t):
collide.append(t)
for t in collide:
things.remove(t)
if key == keys.S:
positions = []
for t in things:
positions.append([t.image,t.x,t.y])
print(positions)
def draw():
screen.fill('black')
player.draw()
for t in things:
t.draw()
pgzrun.go()
```
[DAY-84] Lists
Lets visualize the list, try to delete from the middle, and see how the indexes change.
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
player = Actor("c1")
things = []
def on_key_down(key):
speed = 10
if key == keys.UP:
player.y -= speed
if key == keys.DOWN:
player.y += speed
if key == keys.LEFT:
player.x -= speed
if key == keys.RIGHT:
player.x += speed
if key == keys.F:
f = Actor("flower")
f.x = player.x
f.y = player.y
things.append(f)
if key == keys.R:
f = Actor("rock")
f.x = player.x
f.y = player.y
things.append(f)
if key == keys.U:
things.pop()
if key == keys.D:
collide = []
for t in things:
if player.colliderect(t):
collide.append(t)
for t in collide:
things.remove(t)
def draw():
screen.fill('black')
player.draw()
for i in range(len(things)):
t = things[i]
t.draw()
screen.draw.text(str(i), color=(255,255,255), topleft=(t.x,t.y))
if i > 0:
p = things[i-1]
screen.draw.line((p.x,p.y), (t.x,t.y), (255,255,255))
pgzrun.go()
```
spend more time thinking about connecting previous and current elements from a list, think about how to do it the other way around, from current element to next:
```
change this to go from t to the next element of things, instead from t to previous
for i in range(len(things)):
t = things[i]
...
if i > 0:
p = things[i-1]
...
```
[DAY-85] List; Functions
This day is more about reading than writing, those are few different examples you can use
don't let the zombie flowers overrun you, smash them with rocks
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
game_over = False
elf = Actor("c1")
elf.x = WIDTH/2
elf.y = HEIGHT-20
flowers = []
rocks = []
game_area = Rect((0, 0), (WIDTH, HEIGHT-40))
def add_one_row():
lastY = 0
if len(flowers) > 0:
f = flowers[len(flowers)-1]
lastY = f.y
for i in range(20, WIDTH-10, 20):
f = Actor("flower")
f.x = i
f.y = lastY + 10
flowers.append(f)
def rock_out_of_screen():
if len(rocks) > 0:
rocks.pop(0)
def on_key_down(key):
speed = 10
if key == keys.LEFT:
elf.x -= speed
if key == keys.RIGHT:
elf.x += speed
if key == keys.SPACE:
rock = Actor("rock")
rock.x = elf.x
rock.y = elf.y - 20
animate(rock,pos=(rock.x, -100), on_finished=rock_out_of_screen)
rocks.append(rock)
def update():
global game_over
hit = []
for b in rocks:
for f in flowers:
if b.colliderect(f) and random.randint(0,10) > 7:
hit.append(f)
for h in hit:
flowers.remove(h)
for f in flowers:
if not f.colliderect(game_area):
game_over = True
def draw():
if game_over:
screen.draw.text("GAME OVER", color="white", topleft=(10,10))
else:
screen.fill('black')
elf.draw()
for f in flowers:
f.draw()
for r in rocks:
r.draw()
screen.draw.rect(game_area, (200, 0, 0))
add_one_row()
clock.schedule_interval(add_one_row, 5)
pgzrun.go()
```
```
import turtle as t
size = 10
t.pensize(size)
t.left(45)
t.forward(90)
t.circle(45,extent=180)
t.right(90)
t.circle(45,extent=180)
t.forward(90)
t.penup()
t.goto(-35,-35)
t.pendown()
t.write('i love python')
t.penup()
```
```
import turtle as t
import datetime
import time
def deg(h,m,s):
hDeg=(h3600+m 60+s)/(360012) 360
mDeg=(m60+s)/3600 360
sDeg=360/60*s
return (90+hDeg,90+mDeg,90+sDeg)
def show(h, size):
(hDeg,m,s) = deg(h,0,0)
t.penup()
t.goto(0, size)
t.pencolor('white')
t.setheading(hDeg)
t.forward(size)
t.write(str(h))
def klok(size, h, m, s):
t.reset()
(hDeg,mDeg,sDeg) = deg(h,m,s)
t.pendown()
t.pensize(7)
t.bgcolor('black')
t.pencolor('lime')
t.circle(size)
t.penup()
t.goto(0, size)
t.setheading(hDeg)
t.pendown()
t.pencolor('springgreen')
t.forward(size/3)
t.penup()
t.goto(0, size)
t.setheading(mDeg)
t.pendown()
t.pencolor('lawngreen')
t.forward(size/2)
t.penup()
t.pencolor('cyan')
t.goto(0, size)
t.setheading(sDeg)
t.pendown()
t.forward(size-25)
t.penup()
size = 150
while True:
now = datetime.datetime.now()
klok(size,now.hour, now.minute, now.second)
for h in range(1, 13):
show(h,size)
time.sleep(10)
```
Just one rock that hits the zombies above you
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
game_over = False
elf = Actor("c1")
elf.x = WIDTH/2
elf.y = HEIGHT-20
rock = Actor("rock")
rock.x = elf.x + 10
rock.y = elf.y - 20
flowers = []
def add_one_row():
lastY = 0
if len(flowers) > 0:
f = flowers[len(flowers)-1]
lastY = f.y
for i in range(20, WIDTH-10, 20):
f = Actor("flower")
f.x = i
f.y = lastY + 10
flowers.append(f)
def on_key_down(key):
speed = 10
if key == keys.LEFT:
elf.x -= speed
if key == keys.RIGHT:
elf.x += speed
if key == keys.UP:
elf.y -= speed
if key == keys.DOWN:
elf.y += speed
def update():
global game_over
hit = []
for f in flowers:
if rock.colliderect(f) and random.randint(0,10) > 7:
hit.append(f)
for h in hit:
flowers.remove(h)
rock.x -= 1
if rock.x < elf.x - 10:
rock.x = elf.x + 10
rock.y = elf.y - 20
def draw():
screen.fill('black')
elf.draw()
rock.draw()
for f in flowers:
f.draw()
add_one_row()
clock.schedule_interval(add_one_row, 5)
pgzrun.go()
```
[DAY-86] Lists
SNAKE
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
snake = Actor("c1")
snake.x = WIDTH/2
snake.y = HEIGHT-20
apple = Actor("flower")
apple.x = WIDTH/2
apple.y = HEIGHT/2
snake_size = 20
snake_speed = 1
steps = []
direction = "up"
step_size = 1
game_over = False
game_area = Rect(0,0,WIDTH,HEIGHT)
def on_key_down(key):
global direction
if key == keys.LEFT:
direction = "left"
if key == keys.RIGHT:
direction = "right"
if key == keys.UP:
direction = "up"
if key == keys.DOWN:
direction = "down"
def update():
global snake_size, game_over, snake_speed, steps
s = Actor("snake")
s.x = snake.x
s.y = snake.y
steps.append(s)
if len(steps) > snake_size:
steps = steps[-snake_size:]
if direction == "left":
snake.x -= step_size
if direction == "right":
snake.x += step_size
if direction == "up":
snake.y -= step_size
if direction == "down":
snake.y += step_size
if snake.colliderect(apple):
apple.x = random.randint(0,WIDTH)
apple.y = random.randint(0,HEIGHT)
snake_size += step_size * 10
if not snake.colliderect(game_area):
game_over = True
def draw():
screen.fill('black')
if game_over:
screen.draw.text("GAME OVER", color="white", topleft=(10,10))
else:
screen.draw.rect(game_area, (255,0,0))
for s in steps:
s.draw()
snake.draw()
apple.draw()
pgzrun.go()
```
There are few key moments to emphasize, but the most important one is steps = steps[-snake_size:]
.
Try this in IDLE:
x = [1,2,3,4]
print(x[-1])
It will print '4', so in python you can get elements from the back of the list, just as easily as the front, try x[-2]
, now try to get multiple elements from a list, y = x[0:2]
, it will make new list [1,2]
, it is a bit like this code:
x = [1,2,3,4]
y = []
for i in range(0,2):
y.append(x[i])
Now you can also ask python to give you the first 2 elements by saying x[0:2]
or you can ask it for the elements after the second one by doing x[2:len(x)]
, you can omit 0 and len(x)
so it is a bit shorter, x[:2]
and x[2:]
. Sometimes you want the last 2 elements, to do that just say x[-2:len(x)]
or x[-2:]
and that's how we are getting the last snake_size
elements of the steps
list.
Again, x[-2:len(x)]
just means from -2 elements from the end if the list, until the end of the list. It looks scary though.
Similar to this code:
x = [1,2,3,4]
y = []
for i in range(len(x)-2,len(x)):
y.append(x[i])
[DAY-87] Read/Write Files
Its File time!
First lets make a new file, called day-87.txt and we will open it in "w" mode, which means "write", so once we do f.write
it will start from the beginning of the file, we can use "a" (for append) mode as well that would continue appending to the end of the file
```
f = open("day-87.txt", "w")
while True:
a = input("what do you want to write: ")
if a == "quit":
break
f.write(a + "\n")
f.close()
```
Now you can open day-87.txt with Notepad or some other text editor and see what you wrote.
It is important to remember this pattern
Open
Read or Write
Read or Write
Read or Write
Read or Write
...
Close
lets see how you read a file:
f = open("day-87.txt", "r")
data = f.read()
print(data)
Make a game that persists the player position.
```
import pgzrun
import random
HEIGHT = 200
WIDTH = 200
elf = Actor("c1")
elf.x = WIDTH/2
elf.y = HEIGHT-20
try:
x = open("day-87-x.txt", "r")
elf.x = float(x.read())
x.close()
y = open("day-87-y.txt", "r")
elf.y = float(y.read())
y.close()
except IOError:
pass
def on_key_down(key):
speed = 10
if key == keys.LEFT:
elf.x -= speed
if key == keys.RIGHT:
elf.x += speed
if key == keys.UP:
elf.y -= speed
if key == keys.DOWN:
elf.y += speed
if key == keys.S:
x = open("day-87-x.txt", "w")
x.write(str(elf.x))
x.close()
y = open("day-87-y.txt", "w")
y.write(str(elf.y))
y.close()
def draw():
screen.fill('black')
elf.draw()
pgzrun.go()
```
open day-87-x.txt
and day-87-y.txt
to see the positions of X and Y of the elf after you press S
.
One other patter you will see is:
try:
try to do something
except some error:
handle error
There are many many things that could go wrong when you write to or read a file, for example when you read the file might not be created, or you might have no access to read it, or when you write the disk might be full, and there is no more space.
In our example we don't check if our write fails, so if your disk is full the game will crash, but in the beginning we do check for IOError in case the reading fails, and it will if the files are not created yet the very first time you start the game and there is no save yet.
[DAY-88] Flask
Reading exercise, a lot of unfamiliar code
```
from flask import Flask, redirect, request,make_response
import random
app = Flask(name )
tokens = {}
@app.route('/')
def index():
token = request.cookies.get('token')
if token in tokens:
response = make_response("""
welcome to the secure section of the website,
click here to logout
""")
return response
response = make_response("""
<html>
<form action="/login" method="post">
user: <input name="user">
pass: <input type="password" name="pass">
<input type="submit">
</form>
</html>
""")
return response
@app.route('/logout')
def logout():
token = request.cookies.get('token')
try:
del tokens[token]
except KeyError:
pass
response = make_response(redirect('/'))
response.set_cookie('token', '')
return response
@app.route('/login', methods = ['POST'])
def login():
user = request.form['user']
password = request.form['pass']
if user == "admin" and password == "123":
token = str(random.randint(0,10000000))
tokens[token] = "admin"
response = make_response(redirect('/'))
response.set_cookie('token', token)
return response
else:
return "access denied"
if name == "main ":
app.run(host="127.0.0.1",port=8000,debug=True)
```
start the script, see what it does, try to debug how tokens
changes. Inspect your cookies, try to hack it, login from private mode and steal the cookie from the console.
[DAY-89] Files; Strings; Lists
super simple text editor
Reading exercise, make a text editor, save with ctrl+s
and quit with ctrl+q
```
import pgzrun
import random
HEIGHT = 480
WIDTH = 640
filename = "example.py"
lines = [[]]
cursor_row = 0
cursor_col = 0
try:
x = open(filename, "r")
for c in x.read():
if c== '\n' or c == '\r':
lines.append([])
cursor_row += 1
cursor_col = 0
else:
lines[cursor_row].append(c)
cursor_col += 1
x.close()
except IOError:
pass
def lines_to_string():
s = ''
for r in lines:
for c in r:
s += c
s += '\n'
return s
def on_key_down(key, mod, unicode):
global cursor_row, cursor_col
if key == keys.Q and mod == keymods.LCTRL:
exit()
if key == keys.S and mod == keymods.LCTRL:
x = open(filename, "w")
s = lines_to_string()
x.write(s)
x.close()
elif key == keys.LEFT:
if cursor_col > 0:
cursor_col -= 1
elif key == keys.RIGHT:
if cursor_col < len(lines[cursor_row]):
cursor_col += 1
elif key == keys.UP:
if cursor_row > 0:
cursor_row -= 1
if cursor_col > len(lines[cursor_row]):
cursor_col = len(lines[cursor_row])
elif key == keys.DOWN:
if cursor_row < len(lines) - 1:
cursor_row += 1
if cursor_col > len(lines[cursor_row]):
cursor_col = len(lines[cursor_row])
elif key == keys.BACKSPACE:
if cursor_col == 0:
if cursor_row >= 1:
row = lines.pop(cursor_row)
cursor_col = len(lines[cursor_row-1])
for c in row:
lines[cursor_row-1].append(c)
cursor_row -= 1
else:
row = lines[cursor_row]
if len(row) > 0:
cursor_col -= 1
row.pop(cursor_col)
elif key == keys.RETURN:
# get the rest of the lines
left = []
right = []
if cursor_col < len(lines[cursor_row]):
# split the line if we are pressing enter in the middle
row = lines[cursor_row]
left = row[:cursor_col]
right = row[cursor_col:]
if cursor_row < len(lines):
lines[cursor_row] = left
cursor_col = 0
cursor_row += 1
lines.insert(cursor_row, right)
elif len(unicode) > 0 and ord(unicode) >= 20 and ord(unicode) <= 125:
lines[cursor_row].insert(cursor_col, unicode)
cursor_col += 1
def draw():
screen.fill('black')
screen.draw.text(filename + ", " + str(cursor_row) + ":" + str(cursor_col), (0,0), fontsize=20,fontname="437-win", color="green")
x = 0
y = 30
stepX = 10
stepY = 22
for (index_row, row) in enumerate(lines):
for (index_col, c) in enumerate(row):
screen.draw.text(c, (x,y), fontsize=20,fontname="437-win")
x += stepX
y += stepY
x = 0
cursorX = cursor_col * stepX
cursorY = 30 + (cursor_row * stepY)
screen.draw.rect(Rect((cursorX,cursorY,stepX,stepY)), (255,0,0))
pgzrun.go()
```
write some python, and then run it with python3 example.py
[DAY-90] Strings
Write a super simple text editor. Start by thinking about the problem. How can you display a character on the screen? How can you get the input from the user? How are you going to deal with new lines?
```
import pgzrun
HEIGHT = 480
WIDTH = 640
text = ''
def on_key_down(key, mod, unicode):
global text
if key == keys.Q and mod == keymods.LCTRL:
exit()
elif key == keys.BACKSPACE:
if len(text) > 0:
text = text[:len(text)-1]
elif key == keys.RETURN:
text += '\n'
elif len(unicode) > 0 and ord(unicode) >= 20 and ord(unicode) <= 125:
text += unicode
def draw():
screen.fill('black')
x = 0
y = 0
stepX = 10
stepY = 22
for c in text:
if c == '\n':
y += stepY
x = 0
else:
screen.draw.text(c, (x,y), fontsize=20,fontname="437-win")
x += stepX
screen.draw.rect(Rect((x,y,stepX,stepY)), (255,0,0))
pgzrun.go()
```
This is kind of what screen.draw.text
does, you can of course just do screen.draw.text(text, (0,0), fontsize=20,fontname="437-win")
and it will work fine, instead of displaying character by character and computing our own char spacing, but what is the fun in that? Also this way we are one step closer to be able to move the cursor left and right so we can edit in the middle of the text.
[DAY-91] Lists
list your favorite games, and rank them
```
games = [
["mario smash bros", 3],
["mario party", 4],
["super mario", 2]
]
while True:
for game in games:
print(game[0])
what = input("which game are you interested in: ")
for game in games:
if what in game[0]:
print("i like " + game[0] + ", score: " + str(game[1]))
```
print the lyrics of songs:
```
songs = [
["wellerman", """There once was a ship that put to sea
The name of the ship was the Billy of Tea
The winds blew up, her bow dipped down
Oh blow, my bully boys, blow (huh)
Soon may the Wellerman come
To bring us sugar and tea and rum
One day, when the tonguing is done
We'll take our leave and go"""],
]
while True:
what = input("which song are you interested in: ")
for song in songs:
if what in song[0]:
print('-' * 40)
print(song[1])
print('-' * 40)
```
[DAY-92] Command Line; Command Line Arguments; Files
Today is command line day.
First quickly go back to the start and read about files and folders (directories).
The same way functions can get parameters, your program can get parameters as well, try this:
import sys
print(sys.argv)
save it as a.py
and then run python3 a.py hello those are paremeters
from the Terminal app, you will see ['a.py', 'hello', 'those', 'are', 'paremeters']
, sys.argv[0] is the name of the program, and then the parameters you gave it.
Now lets make few handy programs to help us with our command line:
xcat.py
```
import sys
x = open(sys.argv[1], "r")
data = x.read()
print(data)
```
xls.py
```
import os
import sys
files = os.listdir(sys.argv[1])
files.sort()
for f in files:
if os.path.isdir(f):
print(f + "/")
else:
print(f)
```
xed.py
```
import sys
import os
text = ''
filename = sys.argv[1]
try:
f = open(filename, "r")
text = f.read()
f.close()
except IOError:
pass
while True:
what = input("> ")
if what == '?':
print("""
* ? - help
* p - print
* s - save
* d [n] - delete last N lines
* a text - append text to the end
""")
elif what == 'q':
sys.exit(0)
elif what == 'p':
print(text, end = '')
elif what == 's':
f = open(filename, "w")
f.write(text)
f.close()
elif what[0] == 'a' and what[1] == ' ':
text += what[2:] + '\n'
elif what[0] == 'd':
lines = text.split('\n')
n = 1
if len(what) > 2:
n = int(what[2:])
for i in range(0, n):
lines.pop()
text = "\n".join(lines)
else:
print("* use ? for help")
```
OK now we have a text editor, a program to list files, and a program to print the file's content, now we can use our programs to write more programs :)
try this:
```
$ python3 xed,py example.py
a for i in range(100)
a print(i)
p
s
$ python3 xls.py .
$ python3 xcat.py example.py
$ python3 example.py
```
[DAY-93] PyDoc
Reading docs. type this in the terminal: pydoc3 open
pydoc3 input
pydoc3 print
and pydoc3 pgzero.actor
.
Lets take open
as an example.
```
Help on built-in function open in module io:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
Open file and return a stream. Raise OSError upon failure.
file is either a text or byte string giving the name (and the path
if the file isn't in the current working directory) of the file to
be opened or an integer file descriptor of the file to be
wrapped. (If a file descriptor is given, it is closed when the
returned I/O object is closed, unless closefd is set to False.)
mode is an optional string that specifies the mode in which the file
is opened. It defaults to 'r' which means open for reading in text
mode. Other common values are 'w' for writing (truncating the file if
it already exists), 'x' for creating and writing to a new file, and
'a' for appending (which on some Unix systems, means that all writes
append to the end of the file regardless of the current seek position).
In text mode, if encoding is not specified the encoding used is platform
dependent: locale.getpreferredencoding(False) is called to get the
current locale encoding. (For reading and writing raw bytes use binary
mode and leave encoding unspecified.) The available modes are:
========= ===============================================================
Character Meaning
--------- ---------------------------------------------------------------
'r' open for reading (default)
'w' open for writing, truncating the file first
'x' create a new file and open it for writing
'a' open for writing, appending to the end of the file if it exists
'b' binary mode
't' text mode (default)
'+' open a disk file for updating (reading and writing)
'U' universal newline mode (deprecated)
========= ===============================================================
The default mode is 'rt' (open for reading text). For binary random
access, the mode 'w+b' opens and truncates the file to 0 bytes, while
'r+b' opens the file without truncation. The 'x' mode implies 'w' and
raises an `FileExistsError` if the file already exists.
Python distinguishes between files opened in binary and text modes,
even when the underlying operating system doesn't. Files opened in
binary mode (appending 'b' to the mode argument) return contents as
bytes objects without any decoding. In text mode (the default, or when
't' is appended to the mode argument), the contents of the file are
returned as strings, the bytes having been first decoded using a
platform-dependent encoding or using the specified encoding if given.
'U' mode is deprecated and will raise an exception in future versions
of Python. It has no effect in Python 3. Use newline to control
universal newlines mode.
buffering is an optional integer used to set the buffering policy.
Pass 0 to switch buffering off (only allowed in binary mode), 1 to select
line buffering (only usable in text mode), and an integer > 1 to indicate
the size of a fixed-size chunk buffer. When no buffering argument is
given, the default buffering policy works as follows:
* Binary files are buffered in fixed-size chunks; the size of the buffer
is chosen using a heuristic trying to determine the underlying device's
"block size" and falling back on `io.DEFAULT_BUFFER_SIZE`.
On many systems, the buffer will typically be 4096 or 8192 bytes long.
* "Interactive" text files (files for which isatty() returns True)
use line buffering. Other text files use the policy described above
for binary files.
encoding is the name of the encoding used to decode or encode the
file. This should only be used in text mode. The default encoding is
platform dependent, but any encoding supported by Python can be
passed. See the codecs module for the list of supported encodings.
errors is an optional string that specifies how encoding errors are to
be handled---this argument should not be used in binary mode. Pass
'strict' to raise a ValueError exception if there is an encoding error
(the default of None has the same effect), or pass 'ignore' to ignore
errors. (Note that ignoring encoding errors can lead to data loss.)
See the documentation for codecs.register or run 'help(codecs.Codec)'
for a list of the permitted encoding error strings.
newline controls how universal newlines works (it only applies to text
mode). It can be None, '', '\n', '\r', and '\r\n'. It works as
follows:
* On input, if newline is None, universal newlines mode is
enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
these are translated into '\n' before being returned to the
caller. If it is '', universal newline mode is enabled, but line
endings are returned to the caller untranslated. If it has any of
the other legal values, input lines are only terminated by the given
string, and the line ending is returned to the caller untranslated.
* On output, if newline is None, any '\n' characters written are
translated to the system default line separator, os.linesep. If
newline is '' or '\n', no translation takes place. If newline is any
of the other legal values, any '\n' characters written are translated
to the given string.
If closefd is False, the underlying file descriptor will be kept open
when the file is closed. This does not work when a file name is given
and must be True in that case.
A custom opener can be used by passing a callable as *opener*. The
underlying file descriptor for the file object is then obtained by
calling *opener* with (*file*, *flags*). *opener* must return an open
file descriptor (passing os.open as *opener* results in functionality
similar to passing None).
open() returns a file object whose type depends on the mode, and
through which the standard file operations such as reading and writing
are performed. When open() is used to open a file in a text mode ('w',
'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open
a file in a binary mode, the returned class varies: in read binary
mode, it returns a BufferedReader; in write binary and append binary
modes, it returns a BufferedWriter, and in read/write mode, it returns
a BufferedRandom.
It is also possible to use a string or bytearray as a file for both
reading and writing. For strings StringIO can be used like a file
opened in a text mode, and for bytes a BytesIO can be used like a file
opened in a binary mode.
```
It's a lot! But I guarantee you its the best way to learn about something, the people who wrote the open
function, wrote text to help anyone who is going to use it, describging what it does and how it behaves. It is always worth reading the docs of functions you are going to use. Sometimes they are not very good, but it is worth checking it out.
The other way find things is to google python3 open
and you will usually see stackoverflow answers and maybe some examples, in many cases they will be incomplete or wrong, or pure scam 'pay 10$ to buy our video to learn how to use python3 open'
You can also do pydoc3 on modules, e.g. pydoc3 sys
or pydoc3 sys.argv
. Sometimes it might look a bit intimidating, but its usually much better than using google.
Try also pydoc3 pgzero
, pydoc3 pygame
and pydoc3 pygame.Rect
. There is also a way to find documentation for the command line programs, try man python3
, man
from manual
, if you want to search for something use man -k something
for example man -k python
.
[DAY-94] Editors - Ed/Nano/Vi/Emacs..
Command line editors:
super easy to use, press ctrl+x to exit, ctrl+k to cut text, and ctrl+u to uncut (paste)
Type vimtutor
to see how it works, to quit use ESC
then type :
and then q!
emacs is my favorite editor, in in fact I am writing this book using it. type ctrl+x ctrl+c
to quit, and ctrl+x ctrl+s
to save.
ed is super old editor, it is somewhat similar to xed.py that you wrote, its called 'line editor'. To quit use q
or Q
if you want to quit without saving, to print the contents of the file use 1,$n
which prints the lines from 1 to $, or you can print specific line with 1n
or 2n
where 1 or 2 is the linue number.
try this:
$ ed zzz
a
for i in range(10);
print(i)
.
w
31
1,$n
1 for i in range(10);
2 print(i)
q
a
will append to the file, w
will save the file, 1,$n
will print the contents, and q
will quit. Commands like a,i,d
(append,insert,delete) take line numbers as parameters as well. Use man ed
to see the docs.
I don't think anyone uses ed
anymore, at least not as a text editor, but sometimes its handy to know how to use it.
There are many many text editors, and some are better for you than others, but to me I dont really care, I want to type in my program and save it.. its not the end of the world if I use one or another editor.
So use the one you like most, but sometimes you will go on another computer and they wont have your editor there, so be be sure to be 'ok' with vim, nano or emacs, because they are on virtually any system.
[DAY-95] Memory; Virtual Computer; Instructions; Strings; Lists
Memory.
Lets make a huuuuuge list.
```
memory = []
for i in range(1000000):
memory.append(0)
```
Our memory looks like this:
[0,0,0,..............0,0,0,0....0,0,0,0,0]
Now we can make variables in this list of numbers, by addressing each variable with its index in the list, for exampke x
can be at index 1000 and y
can be at position 1001.
```
def add(a_address,b_address):
return memory[a_address] + memory[b_address]
x_address = 1000
y_address = 1001
memory[x_address] = 5
memory[y_address] = 10
r = add(x_address,y_address)
print(r)
```
This is cheating though, because python uses its own memory to store the result from x and y, lets fix that:
```
def add(a_address,b_address,r_address):
memory[r_address] = memory[a_address] + memory[b_address]
x_address = 1000
memory[x_address] = 5
y_address = 1001
memory[y_address] = 10
r_address = 1002
add(x_address,y_address,r_address)
print(memory[r_address])
```
This is how our memory looks like
```
[....0,0,0,5,10,15,0,...]
^ ^ ^
| | |
x | |
y |
r
x at index 1000
y at index 1001
r at index 1002
```
The code above translates roughly to:
x = 5
y = 10
r = x + y
print(r)
How about strings? We can store strings by just defining how big the string is, and then follow with the characters of the string. You see how it is continous piece of memory.
```
h_address = 2000
memory[h_address] = 5
memory[h_address+1] = ord('h')
memory[h_address+2] = ord('e')
memory[h_address+3] = ord('l')
memory[h_address+4] = ord('l')
memory[h_address+5] = ord('o')
def xprint(address):
l = memory[address]
for i in range(l):
# +1 is because of the length
c = memory[address + 1 + i]
print(chr(c), end = '')
print('')
```
Strings with without length. We can also just say 'the string ends with 0' so start reading and stop when you see 0.
```
n_address = 3000
memory[n_address+0] = ord('h')
memory[n_address+1] = ord('e')
memory[n_address+2] = ord('l')
memory[n_address+3] = ord('l')
memory[n_address+4] = ord('o')
def nprint(address):
for addr in range(address, len(memory)):
c = memory[addr]
if c == 0:
break
print(chr(c), end = '')
print('')
nprint(n_address)
```
Now lets add a funciton to add two strings:
```
a_address = 4000
memory[a_address] = 5
memory[a_address+1] = ord('h')
memory[a_address+2] = ord('e')
memory[a_address+3] = ord('l')
memory[a_address+4] = ord('l')
memory[a_address+5] = ord('o')
b_address = 4006
memory[b_address] = 5
memory[b_address+1] = ord('w')
memory[b_address+2] = ord('o')
memory[b_address+3] = ord('r')
memory[b_address+4] = ord('l')
memory[b_address+5] = ord('d')
c_address = 7000
def xadd(a,b,dst):
len_a = memory[a]
len_b = memory[b]
memory[dst] = len_a + len_b
for i in range(len_a):
c = memory[a + 1 + i]
memory[dst + 1 + i] = c
for i in range(len_b):
c = memory[b + 1 +i]
memory[dst + 1 + len_a + i] = c
xadd(a_address, b_address, c_address)
xprint(c_address)
```
You see, the list is just a list with 1 million numbers, but we decide what those numbers mean, if we are reading a string, we know that the first number represents the length of the string, so its just an integer, but we know that the other numbers are actually characters.
```
i_address = 3996
memory[i_address] = 9999
[....9999,0,0,0,5,104,101,108,108,111,5,119,111,114,108,100....]
^ ^ ^
i this is a this is b
idx: 3996 idx: 4000 idx: 4006
```
The memory doesnt care, string integers, characters,, its all the same. It doesn't know where one array ends or begins. You just read and write to specific address and thats all it cares about. WHERE to read and write.
Think about what it means to remove a character from our string, if its the last character we can sinply reduce the lengthm but lets say we want to remove 'o' from 'world', that would mean something like:
```
world
reduce the length to 4
move r to the left
move l to the left
move d to the left
```
You see we had to do 4 things to remove 1 character, and imagine if the string is 10000 chars long and we want to remove the first one, we wikl have to do 999 things, moving each character to the left.
In the same time, it is super easy to go to specific character, if I want to print the 3rd char, I can just do memory[address + 1 + 3] and thats it, add 1 because of the length and then add however many characters i want to skip.
There are different way to store collections of things, Linked Lists are one example
```
[0, value] # w
|
[next_address, value] # o
|
[next_address, value] # r
|
[next_address, value] # l
|
[0, value ] # d
```
Arrays and Lists are very differentm arrays are always continous, like strings, actually string is just an array of characters. Lists however can be on scattered amongst the memory, and each element can point to the next one.
So with a linked list it is hard to get to position 3 for example, because we have to start from the top, and go down until we see 3 elements, so we have to do 3 things to get to position 3, or 1000 things to get to position 1000. In the same time if we want to remove something, we can simply make it disappear, by making the previous element point to the next one, e.g. make o
point to l
, and then r
will disappear.
Our format will be (next element from the list, value)
```
memory[20000] = 30000
memory[20001] = 1
memory[30000] = 30500
memory[30001] = 2
memory[30500] = 30605
memory[30501] = 3
memory[30605] = 0
memory[30606] = 4
```
the memory now looks like this:
[ ....30000, 1, .... 30500, 2, .... 30605, 3, .... 0, 4, ...]
^ ^ ^ ^
first second third forth element
This is an example function that will print all the values in a linked list, following the links.
```
def lprint(start_address):
done = False
while not done:
# check if this is the last element of the list
done = memory[start_address] == 0
# print the value at address + 1
print(memory[start_address+1])
# go to the next element from the list
start_address = memory[start_address]
lprint(20000)
```
You see, having a flat area of memory is so powerfull! it doesnt know anything about what we store in it, so of course we can store pointers to other parts of the memory, we can have lists of lists of lists of lists that just point around, and of course we can have infinite loops, imagine a linked list where one of the elements points to a previous elemnent.
Check this out:
```
memory[20000] = 30000
memory[20001] = 1
memory[30000] = 20000
memory[30001] = 2
lprint(20000)
```
Inifinite loop! How cool is that!
1
2
1
2
1
2
1
2
1
2
1
2
1
2
1
2
Lets make a computer, it needs Memory and CPU, the CPU will read instructions from memory and produce results back in memory.
```
memory = []
for i in range(1000000):
memory.append(0)
memory[1000] = 5 # a
memory[1001] = 10 # b
memory[1002] = 0 # result
lets multiply a * b
the code looks like this
counter = b
while counter > 0:
r = r + a
counter -= 1
print(r)
counter = b
memory[1003] = memory[1001]
jump to position 10 if counter is 0
memory[0] = 4
memory[1] = 1003
memory[2] = 13
r = r + a
memory[3] = 1
memory[4] = 1002
memory[5] = 1000
memory[6] = 1002
since our add operation adds two things in memory, we
need to store the value -1 somewhere to subtract it from the counter
counter -= 1
memory[9999] = -1
memory[7] = 1
memory[8] = 1003
memory[9] = 9999
memory[10] = 1003
go back to the if counter == 0 instruction
memory[11] = 5
memory[12] = 0
print(r)
memory[13] = 3
memory[14] = 1002
stop the program
memory[15] = 0
position = 0
while True:
instruction = memory[position]
print('instruction',instruction, 'position',position)
# quit if instruction is 0
if instruction == 0:
break
# add position+1 and position+2 and write result in position+3
elif instruction == 1:
a_address = memory[position+1]
b_address = memory[position+2]
r_address = memory[position+3]
memory[r_address] = memory[a_address] + memory[b_address]
position += 4
# print position + 1
elif instruction == 3:
address = memory[position+1]
print(memory[address])
position+=2
# if memory[position+1] is 0 jump to positon+2, else continue to position+3
elif instruction == 4:
address = memory[position+1]
if memory[address] == 0:
position = memory[position+2]
else:
position += 3
# jump to value of position+1
elif instruction == 5:
position = memory[position+1]
```
start the computer and see the result!
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 1, 'position', 3)
('instruction', 1, 'position', 7)
('instruction', 5, 'position', 11)
('instruction', 4, 'position', 0)
('instruction', 3, 'position', 13)
50
('instruction', 0, 'position', 15)
Now lets get into variables from first principles, they are nothing but handy pointers to memory, that you can name yourself, and then you can access this memory by the name you chose.
This is the same program, but we are gonna use A, B, R, COUNTER and MINUS_1 as names for the specific addressess, and you can immidiately see how much cleaner the program looks. We will also name our instructions ADD, JUMP_IF_ZERO (or JZ), PRINT and HALT
```
...
instructions
HALT = 0
ADD = 1
PRINT = 3
JUMP_IF_ZERO = 4
JUMP = 5
variabnles
A = 1000
B = 1001
R = 1002
MINUS_1 = 9999
COUNTER = 1003
program
memory[A] = 5 # A = 5
memory[B] = 10 # B = 5
memory[R] = 0 # R = 0
memory[COUNTER] = memory[B] # COUNTER = B
jump to position 10 if counter is 0
memory[0] = JUMP_IF_ZERO
memory[1] = COUNTER
memory[2] = 13
r = r + a
memory[3] = ADD
memory[4] = R
memory[5] = A
memory[6] = R
counter -= 1
memory[MINUS_1] = -1
counter = counter + minus_1
memory[7] = ADD
memory[8] = COUNTER
memory[9] = MINUS_1
memory[10] = COUNTER
go back to the if counter == 0 instruction
memory[11] = JUMP
memory[12] = 0
print(r)
memory[13] = PRINT
memory[14] = R
stop the program
memory[15] = HALT
...
```
The whole program is actually quite small:
[4, 1003, 13, 1, 1000, 1002, 1002, 1, 1003, 9999, 1003, 5, 0, 3, 1002, 0]
^ ^
jump to 13 if memory[1003] is zero jump to 0
[DAY-95] Memory; Machine Code; Virtual Computer
It will be super nice if our multiply program can be used from multiple places from a bigger program:
...
r = multiply(5, 10)
print(r)
...
We can kind of do that, by just using jump, and carefully writing the multiply function in such a way, that when it is done, to jump back to where we called it. We also have to give it some values to work with, in our case 5 and 10.
We will use a simple list to append the values and the return address, and then pop them out in the right order to use them. Our multiply function has to know how many values to read and it must know which one of them is the return address. [5, 10, ZZZ]
imagine ZZZ is the address where we should return after we have computed the result. And then the function will just do POP, POP, POP and know, first POP will be ZZZ, second pop will be one parameter, third pop will be another parameter. Do what it does with the parameters, and then append its result into the stack, then the caller must know to POP it.
It is called a stack because it is like a stack of things on top of each other (cards for example), you can append(push) one to the top, or remove one from the top (pop). When we pop() we will remove the last thing we push()ed.
If I push 1,2,3 then if i pop 3 times I will print 3 2 1
```
stack = [1,2,3]
print(stack.pop())
print(stack.pop())
print(stack.pop())
```
Here is our updated program, and computer:
```
memory = []
for i in range(1000000):
memory.append(0)
HALT = 0
ADD = 1
PRINT = 3
JUMP_IF_ZERO = 4
JUMP = 5
PUSH = 8
POP = 9
SET = 10
JUMPV = 11 # same as jump, but jumps to the
# value of the address instead of the address itself
# so jumpv 9, will jump to the value of memory[9]
PUSHV = 12 # same as jumpv but for push
just used for debug
instruction_lookup = dict([
(HALT , 'HALT'),
(ADD , 'ADD'),
(PRINT , 'PRINT'),
(JUMP_IF_ZERO , 'JUMP_IF_ZERO'),
(JUMP , 'JUMP'),
(PUSH , 'PUSH'),
(POP , 'POP'),
(SET , 'SET'),
(PUSHV , 'PUSHV'),
(JUMPV , 'JUMPV')
])
# pushv 9, will push memory[9] instead of 9
constants addressess
there is no such thing as constants though, we just think of them as such
MINUS_1 = 9999
set "global" variable MINUS_1 to -1
memory[MINUS_1] = -1 # minus_1 = -1
MAIN FUNCTION
main function has only one variable, the MULTIPLY_RESULT
MULTIPLY_RESULT = 1000
MULTIPLY_RESULT = multiply (5, 10)
memory[0] = PUSH # | |
memory[1] = 5 # ^ |
memory[2] = PUSH # |
memory[3] = 10 # >--+
memory[4] = PUSH # >-------------+
memory[5] = 8 # | after the function is called
memory[6] = JUMP # | jump to get the value
memory[7] = 198 # | from the stack
memory[8] = POP # <-------------+
memory[9] = MULTIPLY_RESULT #
memory[10] = PRINT
memory[11] = MULTIPLY_RESULT
# MULTIPLY FUNCTION
get the value of A
A = 9000
B = 9001
COUNTER = 9003
R = 9004
BACK_TO_ADDRESS = 9005
get the value for where to return to
memory[198] = POP
memory[199] = BACK_TO_ADDRESS
get the value for A
memory[200] = POP
memory[201] = A
get the value for B
memory[202] = POP
memory[203] = B
COUNTER = B (which is counter = 0 ; counter = counter + b)
COUNTER = 0
memory[204] = SET
memory[205] = COUNTER
memory[206] = 0
COUNTER = COUNTER + B
memory[207] = ADD
memory[208] = COUNTER
memory[209] = B
memory[210] = COUNTER
the actual loop
memory[211] = JUMP_IF_ZERO
memory[212] = COUNTER
memory[213] = 224
r = r + a
memory[214] = ADD
memory[215] = A
memory[216] = R
memory[217] = R
since our add operation adds two things in memory, we
need to store the value -1 somewhere to subtract it from the counter
counter -= 1
memory[218] = ADD
memory[219] = COUNTER
memory[220] = MINUS_1
memory[221] = COUNTER
go back to the if counter == 0 instruction
memory[222] = JUMP
memory[223] = 211
return(r)
memory[224] = PUSHV
memory[225] = R
memory[226] = JUMPV
memory[227] = BACK_TO_ADDRESS
start the computer from position 80, we will use positions up-to 80 for our function call stack
position = 0
stack = []
while True:
instruction = memory[position]
print(instruction_lookup[instruction], 'position',position, 'stack', stack)
# quit if instruction is 0
if instruction == HALT:
break
# add position+1 and position+2 and write result in position+3
elif instruction == ADD:
a_address = memory[position+1]
b_address = memory[position+2]
r_address = memory[position+3]
memory[r_address] = memory[a_address] + memory[b_address]
position += 4
# print position + 1
elif instruction == PRINT:
address = memory[position+1]
print(memory[address])
position+=2
# if memory[position+1] is 0 jump to positon+2, else continue to position+3
elif instruction == JUMP_IF_ZERO:
address = memory[position+1]
if memory[address] == 0:
position = memory[position+2]
else:
position += 3
# jump to value of position+1
elif instruction == JUMP:
position = memory[position+1]
elif instruction == JUMPV:
position = memory[memory[position+1]]
elif instruction == PUSH:
stack.append(memory[position+1])
position += 2
elif instruction == PUSHV:
stack.append(memory[memory[position+1]])
position += 2
elif instruction == POP:
memory[memory[position+1]] = stack.pop()
position += 2
elif instruction == SET:
memory[position+1] = memory[position+2]
position += 3
```
We cheated a bit by using python's lists instead of our own list to do the stack. We could reserve some memory (e.g. 100000 to 200000) and just push and pop the values there, memory[100000] will just say how many elements we have in the stack, and PUSH will do memory[[memory[100000]] = value, memory[100000] += 1
, and pop will do memory[100000] -= 1
and use memory[memory[100000]]
as value.
You see how powerfull are continous pieces of memory? Arrays and Lists are how computers are built!
Look. In reallity more things happen, and actually normal machine code is easier than this, you can store values in temporary places called registers, and access them really fast and nobody actually writes code like that, we use languages such as Assembler to help us, and using assemblers we built other languages, such as C, and with C we built others, such as python, and then with python we build whole systems, like instagram or dropbox. You can of course build instagram with machine code if you want, it will just take incredible amount of time, and will be gazillion times more buggy. C is good at some things that python is not, and the other way around.
The one thing you have to remember, is whatever language you are using, whatever program you are looking at, it must have some memory, and some way of modifying that memory, and execute instructions over it.
There is no magic, it is all built on this. Built with few numbers in a block of memory.
Lets examine the output of the program, you see how the stack is empty, then we add 5, 10, and then 8 which will be used from the function to go back to us.
PUSH position 0 stack-before [] stack-after [5]
PUSH position 2 stack-before [5] stack-after [5, 10]
PUSH position 4 stack-before [5, 10] stack-after [5, 10, 8]
JUMP position 6 stack-before [5, 10, 8] stack-after [5, 10, 8]
POP position 198 stack-before [5, 10, 8] stack-after [5, 10]
POP position 200 stack-before [5, 10] stack-after [5]
POP position 202 stack-before [5] stack-after []
SET position 204 stack-before [] stack-after []
ADD position 207 stack-before [] stack-after []
JUMP_IF_ZERO position 211 stack-before [] stack-after []
ADD position 214 stack-before [] stack-after []
ADD position 218 stack-before [] stack-after []
JUMP position 222 stack-before [] stack-after []
JUMP_IF_ZERO position 211 stack-before [] stack-after []
ADD position 214 stack-before [] stack-after []
ADD position 218 stack-before [] stack-after []
JUMP position 222 stack-before [] stack-after []
JUMP_IF_ZERO position 211 stack-before [] stack-after []
ADD position 214 stack-before [] stack-after []
ADD position 218 stack-before [] stack-after []
JUMP position 222 stack-before [] stack-after []
JUMP_IF_ZERO position 211 stack-before [] stack-after []
ADD position 214 stack-before [] stack-after []
ADD position 218 stack-before [] stack-after []
JUMP position 222 stack-before [] stack-after []
JUMP_IF_ZERO position 211 stack-before [] stack-after []
ADD position 214 stack-before [] stack-after []
ADD position 218 stack-before [] stack-after []
JUMP position 222 stack-before [] stack-after []
JUMP_IF_ZERO position 211 stack-before [] stack-after []
PUSHV position 224 stack-before [] stack-after [50]
JUMPV position 226 stack-before [50] stack-after [50]
POP position 8 stack-before [50] stack-after []
PRINT position 10 stack-before [] stack-after []
50
HALT position 12 stack-before []
We could do it the other way, first push the address to go back to, and then the values, which will be the same, we just have to decide, this is called a 'calling convention', convention is just the usuall way to do things. So each program on your computer obeys the calling convention, otherwise a chaos will arrive, imagine multiplying the return address by first paremeter and then returning to some random position in memory.
By now you can see how fragile this is, if one mistake is made, you can corrupt rest of the program, we can easilly write something into where the next instruciton is read, and make the computer halt, or go into infinite loop.
Sometimes we can find bugs in a program that we can exploit, if we can simply control the corruption, we can make it jump to somewhere where we have our own code, and then we can control what the program does.
[DAY-96] Binary; ASCII; Memory
Lets spend a day on bits and bytes.
One bit is the minimum amount of information you can hold, it is either 1 or 0, on or off. If we have a variable that has to store the heads or tails value of a coin, we can store it in 1 bit, lets say 1 is heads, 0 is tails. To store the values of two coins we can use 2 bits.
0 # tails
1 # heads
2 possible
0 0 # both coins are tails
0 1 # second coin is heads
1 0 # first coin is heads
1 1 # both coins are heads
2 * 2 possible
We have 4 distinct values, in 2 bits, lets try 3 coins
000
001
010
011
100
101
110
111
2 * 2 * 2 possible
we have 8 distinct values in 3 bits, and in 4 bits we have 16 distinct values
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
2 * 2 * 2 * 2 possible
in 32 bits we can store 4294967295 distinct values! and in 64 bits we can store 18446744073709551615.
But what about if we want to store the value of a dice? Possible values are 1 2 3 4 5 6. We can do that in just 3 bits.
8 bits make a byte. Usually we need 1 bit of information for the sign of the number, is it - or +, so sometimes you will hear "signed integer" or "unsigned integer", and the difference is the unsigned integers get one more bit to work with, which is a big deal, if the integer is 4 bytes, that is 32 bits, the maximum possible numbmer for signed integer is 2147483647, and the minimum is -2147483647, but unsigned one is from 0 to 4294967295.
The reason is 2 * 2 * 2 * 2 * 2 * 2... 31 times is twice smaller than 2 * 2 * 2 * 2 ... 32 times.
We can also count in this system (called binary system) to make it represent numbers.
try this:
for i in range(255):
print(i, ' -> ', format(i, '08b'))
in python format can take a number and print it as binary number:
0 -> 00000000
1 -> 00000001
2 -> 00000010
3 -> 00000011
4 -> 00000100
5 -> 00000101
6 -> 00000110
7 -> 00000111
8 -> 00001000
9 -> 00001001
10 -> 00001010
11 -> 00001011
12 -> 00001100
13 -> 00001101
14 -> 00001110
15 -> 00001111
16 -> 00010000
...
the rules to count in the binary system are the same in the decimal system, when you go from 9 to 10 you increase the number of digits, but here.. you havbe to do it many more because you habe only 0 and 1.
so you start with 0, then 1, then you are out of numbers, so you add one more and then ext one is 1 0, then 1 1 and then you are out of space again, and go 1 0 0, 1 0 1, 1 1 0, 1 1 1 and so on.
So if you need to store the number x = 47917437
, which in binary is 10110110110010100101111101, you will need 27 bits of space. However there are more limitations, you can usually store only 4 or 8 bytes (so 32 or 64 bits) because of the way the computer is made, so we will just pad it with zeros, and what will get stored on the memory chip is 0000010110110110010100101111101, and python will know the address of that, so when you say 'a = x + 1' it will go to the specific address, read the value, add one to it, and store it back.
example if we want to store 5, h e l l o
, the computer memory might look like this:
```
5 h e l l o
5 104 101 108 108 111
0,0,0,0,0,1,0,1, 0,1,1,0,1,0,0,0, 0,1,1,0,0,1,0,1, 0,1,1,0,1,1,0,0, 0,1,1,0,1,1,0,0, 0,1,1,0,1,1,1,1
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
...
```
If we use 1 byte per character, ASCII actuaklly fitst in 7 bits (its called 7 bit ascii) as the maximum value is 127, but we store things aligned to 1 byte, the way processors are made, they have certain restrictions,m they cant just go and read/write at a specific bit position in the memory, so many times when we want to store 7 bits of data we need to use 8 bits, Unless we come with something to store in the extra bit, it will be just waste.
[DAY-97] Lists;
Catch all the falling snakes.
Take this skeleton, and fill in the blanks.
```
import pgzrun
import random
HEIGHT = 400
WIDTH = 300
falling = []
game_area = Rect(0,0,WIDTH,HEIGHT)
elf = Actor("c1")
elf.y = HEIGHT - 10
elf.x = WIDTH/2
game_over = False
def drop():
f = Actor("snake")
f.x = random.randint(0,WIDTH)
f.y = random.randint(0, 150)
falling.append(f)
def update():
global game_over
# move the elf left or right
...
# detect the collisions between snakes and elf
# and remove them if they collide
...
# advance the snakes downwards
...
# check if the snakes are outside of the game area, and set game over
...
# add new snakes if there are less than 5 on the screen
...
def draw():
if game_over:
screen.fill('pink')
else:
screen.fill('black')
for f in falling:
f.draw()
screen.draw.rect(game_area, (255,0,0))
elf.draw()
pgzrun.go()
```
This is one example of implementing it, can you think of another?
```
import pgzrun
import random
HEIGHT = 400
WIDTH = 300
falling = []
game_area = Rect(0,0,WIDTH,HEIGHT)
elf = Actor("c1")
elf.y = HEIGHT - 10
elf.x = WIDTH/2
game_over = False
def drop():
f = Actor("snake")
f.x = random.randint(0,WIDTH)
f.y = random.randint(0, 150)
falling.append(f)
def update():
global game_over
# move the elf left or right
if keyboard.left:
elf.x = elf.x-5
if keyboard.right:
elf.x = elf.x+5
# detect the collisions between snakes and elf
# and remove them if they collide
remove = []
for f in falling:
if f.colliderect(elf):
remove.append(f)
for r in remove:
falling.remove(r)
# advance the snakes downwards
for f in falling:
f.y += 1
# check if the snakes are outside of the game area, and set game over
for f in falling:
if not f.colliderect(game_area):
game_over = True
# add new snakes if there are less than 5 on the screen
if len(falling) < 5:
drop()
def draw():
if game_over:
screen.fill('pink')
else:
screen.fill('black')
for f in falling:
f.draw()
screen.draw.rect(game_area, (255,0,0))
elf.draw()
pgzrun.go()
```
Another possible implementation, this one uses list()
to make a copy of the falling list and also has score and lives.
```
import pgzrun
import random
HEIGHT = 400
WIDTH = 300
falling = []
game_area = Rect(0,0,WIDTH,HEIGHT)
elf = Actor("c1")
elf.y = HEIGHT - 10
elf.x = WIDTH/2
game_over = False
score = 0
lives = 5
def drop():
f = Actor("snake")
f.x = random.randint(0,WIDTH)
f.y = random.randint(0, 150)
falling.append(f)
def update():
global game_over, score, lives
if keyboard.A:
elf.x -= 5
if keyboard.D:
elf.x += 5
for i in falling:
i.y += 1
for i in list(falling):
if not i.colliderect(game_area):
falling.remove(i)
lives -= 1
game_over = lives <= 0
if len(falling) < 5:
drop()
for i in list(falling):
if i.colliderect(elf):
falling.remove(i)
score += 1
def draw():
if game_over:
screen.fill('pink')
else:
screen.fill('black')
screen.draw.text("score: " + str(score) + " lives: " + str(lives), topleft=(10,10))
for f in falling:
f.draw()
screen.draw.rect(game_area, (255,0,0))
elf.draw()
pgzrun.go()
```
[DAY-98] Lists; Read/Write File
```
import pgzrun
import sys # for sys.exit()
HEIGHT = 300
WIDTH = 300
elf = Actor("c1")
colors = [
[(255,0,0), Rect(0,0,40,40)],
[(0,255,0), Rect(60,0,40,40)],
[(0,0,255), Rect(120,0,40,40)],
]
color = None
pixels = []
def update():
global color, pixels
if keyboard.LEFT:
elf.x -= 2
if keyboard.RIGHT:
elf.x += 2
if keyboard.UP:
elf.y -= 2
if keyboard.DOWN:
elf.y += 2
if keyboard.Q:
sys.exit(0)
if keyboard.SPACE and color != None:
pixels.append([
color,
Rect(elf.x,elf.y,40,40)
])
if keyboard.C:
pixels = []
color = None
if keyboard.D:
drop = Rect(elf.x,elf.y,40,40)
for p in list(pixels):
if drop.colliderect(p[1]):
pixels.remove(p)
for c in colors:
if elf.colliderect(c[1]):
color = c[0]
def draw():
screen.fill('black')
for c in colors:
screen.draw.filled_rect(c[1], c[0])
for p in pixels:
screen.draw.filled_rect(p[1], p[0])
if color != None:
screen.draw.rect(Rect(elf.x,elf.y,40,40), color)
elf.draw()
screen.draw.text(str(len(pixels)), topleft=(10,10))
pgzrun.go()
```
Simple catch the flower game
```
import pgzrun
import sys # for sys.exit()
HEIGHT = 300
WIDTH = 300
elf = Actor("c1")
flower = Actor("flower")
def update():
if keyboard.LEFT:
elf.x -= 5
# add RIGHT/UP/DONW
if keyboard.Q:
sys.exit(0)
# check if the elf collides the flower
# and if it does, increment the score
# and place the flower on some random place
# ...
def draw():
screen.fill('black')
elf.draw()
flower.draw()
# show the score
# ...
pgzrun.go()
```
Example implementation:
```
import pgzrun
import random
import sys # for sys.exit()
HEIGHT = 300
WIDTH = 300
elf = Actor("c1")
elf.x = WIDTH/2
elf.y = HEIGHT/2
flower = Actor("flower")
flower.x = 10
flower.y = 10
score = 0
def update():
global score
if keyboard.LEFT:
elf.x -= 5
if keyboard.RIGHT:
elf.x += 5
if keyboard.UP:
elf.y -= 5
if keyboard.DOWN:
elf.y += 5
if keyboard.Q:
sys.exit(0)
if elf.colliderect(flower):
flower.x = random.randint(10,WIDTH-10)
flower.y = random.randint(10,HEIGHT-10)
score += 1
def draw():
screen.fill('black')
elf.draw()
flower.draw()
screen.draw.text(str(score), topleft=(10,10))
pgzrun.go()
```
Same program but with Load and Save
```
import pgzrun
import sys # for sys.exit()
HEIGHT = 300
WIDTH = 300
elf = Actor("c1")
colors = [
[(255,0,0), Rect(0,0,40,40)],
[(0,255,0), Rect(60,0,40,40)],
[(0,0,255), Rect(120,0,40,40)],
]
color = None
pixels = []
def make_rect_around_actor(a):
return Rect(a.x,a.y,40,40)
def update():
global color, pixels
if keyboard.LEFT:
elf.x -= 2
if keyboard.RIGHT:
elf.x += 2
if keyboard.UP:
elf.y -= 2
if keyboard.DOWN:
elf.y += 2
if keyboard.Q:
sys.exit(0)
if keyboard.SPACE and color != None:
pixels.append([
color,
make_rect_around_actor(elf),
])
if keyboard.C:
pixels = []
color = None
if keyboard.S:
f = open("save.txt", "w")
for p in pixels:
(red,green,blue) = p[0]
f.write(str(red))
f.write(",")
f.write(str(green))
f.write(",")
f.write(str(blue))
f.write(",")
f.write(str(p[1].x))
f.write(",")
f.write(str(p[1].y))
f.write(",")
f.write(str(p[1].width))
f.write(",")
f.write(str(p[1].height))
f.write("\n")
f.close()
if keyboard.L:
pixels = []
f = open("save.txt", "r")
lines = f.readlines()
for l in lines:
(red,green,blue,x,y,w,h) = l.split(",")
pixels.append([
(float(red),float(green),float(blue)),
Rect(float(x),float(y), float(w), float(h))
])
f.close()
if keyboard.D:
drop = make_rect_around_actor(elf)
for p in list(pixels):
if drop.colliderect(p[1]):
pixels.remove(p)
for c in colors:
if elf.colliderect(c[1]):
color = c[0]
def draw():
screen.fill('black')
for c in colors:
screen.draw.filled_rect(c[1], c[0])
for p in pixels:
screen.draw.filled_rect(p[1], p[0])
if color != None:
screen.draw.rect(make_rect_around_actor(elf), color)
elf.draw()
screen.draw.text(str(len(pixels)), topleft=(10,10))
pgzrun.go()
```
[DAY-99] Classes; Lists; Functions; Cartesian Coordinates
Today we talk about classes and instances.
Classes are a bit like the houses you buy in roblox, its just a recepie for a house, and when you buy it you can customize it.
If two people have houses made from the same blueprint, we call them instances, they are seperate entities, you can lock one and that does not mean the other is locked. One can have a couch the other one doesn't.
The blueprint or recipe we call 'class' and the real thing that comes out of it we call 'instance'.
The class can define functions, and those functions will take a magic self
parameter, where self
will be the instance. For example in roblox, the house probably has a function 'lock()' that does something like self.is_locked = True
.
Those functions are called 'methods' and the instance is also called an object. A method is supposed to be a bit like a message to the object, p.colliderect(r)
for example you can look at sending the message colliderect
to the object p
with parameter r
. Or you can look at it just as a function with hidden self
parameter. In the following example you can see a method def colliderect(self,r)
in the Point class, and also a standalone function def collidepoint(rect, point)
that just expects a rect and a point objects.
```
class Point:
x = 0
y = 0
def init (self, name):
self.name = name
def print(self):
print('point',self.x,self.y,self.name)
def colliderect(self,r):
return self.x > r.x and self.x < r.x + r.w and self.y > r.y and self.y < r.y + r.h
class Rect:
x = 0
y = 0
w = 0
h = 0
def print(self):
print('rect',self.x,self.y,self.w,self.h)
|-----------------------+
| |
6 +-------+ |
| | | |
4--|---x | |
| | | | |
2--+-------+ |
| | | | |
+--2---6---9------------+
0,0
def collidepoint(rect, point):
if point.x > rect.x and point.x < rect.x + rect.w and point.y > rect.y and point.y < rect.y + rect.h:
return True
else:
return False
p = Point("blue") # instance
p.x = 6
p.y = 4
r = Rect() # instance
r.x = 2
r.y = 2
r.w = 7
r.h = 4
if collidepoint(r,p):
print("COLLIDES")
r.print()
p.print()
p2 = Point("red")
p2.x = 10
p2.y = 10
if not collidepoint(r,p2):
print("NO COLLISION")
r.print()
p.print()
if p.colliderect(r):
print("p collides")
```
```
import pgzrun
import sys # for sys.exit()
import random
HEIGHT = 600
WIDTH = 600
elf = Actor("c1")
speed = 3
back = []
def update():
global score
if keyboard.A:
elf.x -= speed
if keyboard.D:
elf.x += speed
if keyboard.W:
elf.y -= speed
if keyboard.S:
elf.y += speed
if keyboard.J:
f = Actor('flower')
f.x = elf.x
f.y = elf.y
back.append(f)
if keyboard.M:
f = open("save.txt", "w")
for x in back:
f.write(str(x.x))
f.write(",")
f.write(str(x.y))
f.write("\n")
f.close()
if keyboard.L:
f = open("save.txt", "r")
for line in f.readlines():
(x,y) = line.split(",") # 30,20
a = Actor('flower')
a.x = float(x)
a.y = float(y)
back.append(a)
f.close()
if keyboard.Q:
sys.exit(0)
def draw():
screen.fill('black')
for i in back:
i.draw()
elf.draw()
pgzrun.go()
```
simpler painting game:
```
import pgzrun
import sys # for sys.exit()
import random
HEIGHT = 600
WIDTH = 600
elf = Actor("c1")
speed = 3
back = []
def update():
global score
if keyboard.A:
elf.x -= speed
if keyboard.D:
elf.x += speed
if keyboard.W:
elf.y -= speed
if keyboard.S:
elf.y += speed
if keyboard.J:
f = Actor('flower')
f.x = elf.x
f.y = elf.y
back.append(f)
if keyboard.M:
f = open("save.txt", "w")
for x in back:
f.write(str(x.x))
f.write(",")
f.write(str(x.y))
f.write("\n")
f.close()
if keyboard.L:
f = open("save.txt", "r")
for line in f.readlines():
(x,y) = line.split(",") # 30,20
a = Actor('flower')
a.x = float(x)
a.y = float(y)
back.append(a)
f.close()
if keyboard.Q:
sys.exit(0)
def draw():
screen.fill('black')
for i in back:
i.draw()
elf.draw()
pgzrun.go()
```
[DAY-100] Touch Typing; Lists
Day 100 party!
We will make another touch typing game
```
import pgzrun
import random
HEIGHT = 400
WIDTH = 600
words = []
text = ''
game_over = False
beep = tone.create('A3', 0.5)
def move():
global game_over
for w in words:
w[1]+= random.randint(10,15)
if w[1] > HEIGHT:
game_over = True
def add_word():
common = ['a','about','all','also','and','as','at','be','because','but','by','can','come','could','day',
'do','even','find','first','for','from','get','give','go','have','he','her','here','him','his',
'how','i','if','in','into','it','its','just','know','like','look','make','man','many','me',
'more','my','new','no','not','now','of','on','one','only','or','other','our','out','people',
'say','see','she','so','some','take','tell','than','that','the','their','them','then','there',
'these','they','thing','think','this','those','time','to','two','up','use','very','want','way',
'we','well','what','when','which','who','will','with','would','year','you','your',
]
words.append([random.randint(10,WIDTH-50), random.randint(10,HEIGHT/2), random.choice(common)])
def on_key_down(key, mod, unicode):
global text
if key == keys.BACKSPACE:
if len(text) > 0:
text = text[:-1]
elif len(unicode) > 0 and ord(unicode) >= 65 and ord(unicode) <= 125:
text += unicode
for w in list(words):
if w[2] == text:
words.remove(w)
text = ''
beep.play()
def draw():
if game_over:
screen.fill('pink')
else:
screen.fill('black')
for w in words:
screen.draw.text(w[2], (w[0],w[1]), fontsize=20,fontname="437-win")
screen.draw.text(text, (WIDTH/2,HEIGHT - 40), color=(255,0,0), fontsize=40,fontname="437-win")
for i in range(5):
add_word()
clock.schedule_interval(add_word, 2)
clock.schedule_interval(move, 1)
pgzrun.go()
```
ghost!
```
import random
score = 0
while True:
ghost = random.randint(1,3)
choice = input('Pick a door from 1,2, or 3: ')
if choice == str(ghost):
print ('there is a ghost :O GAME OVER !!!')
break
else:
score += 1
print('lucky no gosht')
print('your score is ' + str(score))
```
[DAY-101] Functions; Strings
invert a list
```
def invert(l):
#...
print(invert([1,2,3]))
```
invert a string
```
def invert(s):
#...
print(invert("hello"))
```
invert a number
```
def invert(n):
#...
print(invert(123456))
```
Check if a string is a palindrome, a palindrome is a string that you can read backwards and it sounds the same.
Anna
civic
kayak
level
madam
mom
noon
racecar
radar
redder
refer
repaper
rotator
rotor
sagas
solos
stats
tenet
wow
Never odd or even.
We panic in a pew.
Won’t lovers revolt now?
Don’t nod.
Sir, I demand, I am a maid named Iris.
Don't nod.
I did, did I?
Step on no pets.
Eva, can I see bees in a cave?
Was it a cat I saw?
example:
while True:
n = input("which string you want to check: )
if is_palindrome(n):
print(n + " is a palindrome")
else:
print(n + " is not a palindrome")
Chapter 14 - Week 14
day0: Basics of Basics
day1: Basics of Basics
day2: Basics of Basics
day3: Basics of Basics
day4: Basics of Basics
day5: Basics of Basics
day6: Basics of Basics
[DAY-102] Touch Typing day
Whole day touch typing!
Modify the program to print some score and words per minute, and try to improve your score.
```
import pgzrun
import random
import time
HEIGHT = 800
WIDTH = 600
words = []
text = ''
game_over = False
beep = tone.create('A3', 0.5)
pause = False
score = 0
times = []
def words_per_minute():
if len(times) < 2:
return 0
return int(len(times) / ((times[-1] - times[0]) / 60.0))
def move():
global game_over
if pause:
return
for w in words:
w[1]+= random.randint(10,15)
if w[1] > HEIGHT:
game_over = True
def add_word():
if pause:
return
common = ['a','about','all','also','and','as','at','be','because','but','by','can','come','could','day',
'do','even','find','first','for','from','get','give','go','have','he','her','here','him','his',
'how','i','if','in','into','it','its','just','know','like','look','make','man','many','me',
'more','my','new','no','not','now','of','on','one','only','or','other','our','out','people',
'say','see','she','so','some','take','tell','than','that','the','their','them','then','there',
'these','they','thing','think','this','those','time','to','two','up','use','very','want','way',
'we','well','what','when','which','who','will','with','would','year','you','your',
'paper','game','remember','person','english','dutch','amsterdam','nothing','sleep','product','natural',
'juice','orange','blue','green','together','friends','between','music','book','bookstore','fish','complete',
'width','weight','height','length','string','python','unicode','backspace','random','choice','string','integer',
'function','print','print','print','for','range','range',
]
w = random.choice(common)
words.append([random.randint(10,WIDTH-(len(w) * 15)), random.randint(10,int(HEIGHT/3)), w])
def on_key_down(key, mod, unicode):
global text, pause, score_words, score
if key == keys.BACKSPACE:
if len(text) > 0:
text = text[:-1]
elif key == keys.SPACE:
pause = not pause
elif len(unicode) > 0 and ord(unicode) >= 65 and ord(unicode) <= 125:
text += unicode
for w in list(words):
if w[2] == text:
score += 1
words.remove(w)
if len(words) < 4:
add_word()
text = ''
beep.play()
times.append(time.time())
def draw():
if game_over:
screen.fill('pink')
elif pause:
screen.fill('magenta')
else:
screen.fill('black')
screen.draw.text("score: " + str(score) + " wpm: " + str(words_per_minute()), (10,10), color=(0,255,0), fontsize=15,fontname="437-win")
for w in words:
screen.draw.text(w[2], (w[0],w[1]), fontsize=20,fontname="437-win")
screen.draw.text(text, (WIDTH/2,HEIGHT - 40), color=(255,0,0), fontsize=40,fontname="437-win")
for i in range(5):
add_word()
clock.schedule_interval(add_word, 5)
clock.schedule_interval(move, 5)
pgzrun.go()
```
get more words with the characters you need to train from your dictionary file
use a simple program like this:
```
import sys
need = ['k','l','i','o']
for line in sys.stdin:
missing = False
s = line.rstrip()
for n in need:
if n not in s:
missing = True
if not missing and len(s) <= 7:
print(s)
```
and then get the list:
cat /usr/share/dict/words | python3 words.py | tr "[A-Z]" "[a-z]" | sort | uniq | sed -e "s/^/'/g" -e "s/$/',/g" | pbcopy
[DAY-103] Read File; Command Line Arguments
Search all the books!
First download https://www.gutenberg.org/cache/epub/feeds/pg_catalog.csv.zip, this is a list of all the books available from the gutenberg project.
Oh! the gutenberg project is absolutely amazing, they have more than 60000 books that have expired copyright.
```
import csv
import sys
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--author', help='match author name')
parser.add_argument('--title', help='match title')
parser.add_argument('--subject', help='match subject')
args = parser.parse_args()
def show(id, title, authors, subjects, issued, language):
print(">>> " + title + " <<<")
print(" " + issued)
print(" https://www.gutenberg.org/ebooks/" + id)
print('')
for a in authors:
print(" Author: " + a)
print('')
for s in subjects:
print(" Subject: " + s)
print(" Language: " + language)
print("-" * 40)
file = open('pg_catalog.csv')
reader = csv.reader(file)
for row in reader:
# ['Text#', 'Type', 'Issued', 'Title', 'Language', 'Authors', 'Subjects', 'LoCC', 'Bookshelves']
id = row[0]
if id == "Text#":
# skip the first row (header)
continue
issued = row[2]
title = row[3].replace("\n","; ")
language = row[4]
authors = row[5].split("; ")
subjects = row[6].split("; ")
match = 0
need = 0
if args.title != None:
need += 1
if args.title in title:
match += 1
if args.subject != None:
need += 1
for s in subjects:
if args.subject in s:
match += 1
break
if args.author != None:
need += 1
for a in authors:
if args.author in a:
match += 1
break
if match == need:
show(id,title,authors,subjects,issued,language)
file.close()
```
now try this:
python3 search.py --title Alice --author Carroll | less
CSV stands for comma separated value, its a neat way to encode a table, each column is separated by a ,
. Python has csv module in its standard library, and its very easy to load and parse csv files.
[DAY-104] Read File; Command Line Arguments; Dictionary
The previous approach can match only with substrings, for example we can not match "Lewis Carroll", because the author name is stored "Carroll, Lewis", in fact we can not even match on "Carroll Lewis" because we will be missing a comma.
Another way to search is if we actually split the strings, and then create an index of which word is contained in which books, very similar to whe you open the back of a book, you see a word(or a topic) and then pages at which it appears.
First just copy paste the program, and try to read it, we will go over it step by step later.
```
import sys
import re
import json
def show(book):
id = book["id"]
title = book["title"]
authors = book["authors"]
subjects = book["subjects"]
issued = book["issued"]
language = book["language"]
print(">>> " + title + " <<<")
print(" " + issued)
print(" https://www.gutenberg.org/ebooks/" + str(id))
print('')
for a in authors:
print(" Author: " + a)
print('')
for s in subjects:
print(" Subject: " + s)
print(" Language: " + language)
print("-" * 40)
def parse(filename):
file = open(filename)
reader = csv.reader(file)
books = []
for row in reader:
# ['Text#', 'Type', 'Issued', 'Title', 'Language', 'Authors', 'Subjects', 'LoCC', 'Bookshelves']
if row[0] == "Text#":
# skip the first row (header)
continue
id = int(row[0])
issued = row[2]
title = row[3].replace("\n","; ")
language = row[4]
authors = row[5].split("; ")
subjects = row[6].split("; ")
book = {
"title": title,
"language": language,
"authors": authors,
"subjects": subjects,
"issued": issued,
"id": id
}
books.append(book)
file.close()
return books
def normalize(s):
# 'Alice's Adventures in Wonderland' -> 'alice's adventures in wonderland'
return s.lower()
def tokenize(s):
# 'alice's adventures in wonderland' -> ['alice','s','adventures','in','wonderland']
return re.split("[^\w+]",s)
def build_search_index(books):
index = {}
for i,book in enumerate(books):
tokens = set()
for token in tokenize(normalize(book["title"])):
k = "title:" + token
tokens.add(k)
for token in tokenize(normalize(book["language"])):
k = "language:" + token
tokens.add(k)
for author in book["authors"]:
for token in tokenize(normalize(author)):
k = "author:" + token
tokens.add(k)
for subject in book["subjects"]:
for token in tokenize(normalize(subject)):
k = "subject:" + token
tokens.add(k)
for t in tokens:
if not t in index:
index[t] = []
index[t].append(i)
return index
def search(books, index, query):
matching = None
for q in query:
if q in index:
if matching == None:
matching = set(index[q])
else:
matching.intersection_update(index[q])
else:
matching = set() # if one of the terms is not matching, return empty
result = []
if matching == None:
return result
for book_index in matching:
book = books[book_index]
result.append(book)
return result
if len(sys.argv) == 1:
print("usage:\n\t" + sys.argv[0] + " title:alice author:lewis")
sys.exit(1)
data = None
try:
f = open("search.json", mode="r")
data = json.load(f)
f.close()
except IOError:
books = parse("pg_catalog.csv")
search_index = build_search_index(books)
data = {}
data["search"] = search_index
data["books"] = books
f = open("search.json", mode="w")
json.dump(data,f)
f.close()
query = []
for arg in sys.argv[1:]:
query.append(normalize(arg))
for book in search(data["books"], data["search"], query):
show(book)
```
lets try it:
```
% python3 search.py title:Alice author:carroll author:lewis subject:children
Alice's Adventures in Wonderland <<<
2008-06-27
https://www.gutenberg.org/ebooks/11
Author: Carroll, Lewis, 1832-1898
Subject: Fantasy fiction
Subject: Children's stories
Subject: Imaginary places -- Juvenile fiction
Subject: Alice (Fictitious character from Carroll) -- Juvenile fiction
Language: en
...
```
The first time you search it will be slower, but then we will persist the search index on disk, in the search.json file, and then the second time it will be significantly faster because we will not have to do the work of parsing and building the index again, but directly load the precomputed index.
So many new concepts here, but the biggest one are maps and sets.
A map is a data structure (list is a data structure as well), that allows you to find something by a key you store it with.
```
episodes = {}
episodes["naruto"] = 220
episodes["naruto shippuuden"] = 500
episodes["boruto"] = 215
print(episodes)
print(episodes["naruto"])
if "naruto" in episodes:
print("naruto is in the map")
for k in episodes:
print(k)
for k in episodes:
print(k, episodes[k])
```
A set is a just a bag of things, for example when you put your toys in a bag, the bag is a set containing your toys. Lets make a set of flowers.
```
flowers = set()
flowers.add("rose")
flowers.add("camomile")
flowers.add("tulip")
if "tulip" in flowers:
print("tulip is in the set")
for f in flowers:
print(f)
```
You can union
two sets of yoys by placing them into a new bag and this will contain both sets of toys, or you can intersect
them by only taking toys that exist in both bags.
Both maps and sets are somewhat related, imagine a map that only contains keys.
This is very very shallow explanation, but will do for now, we will spend the next 3-4 months with sets and maps things will get clearer.
[DAY-105] Basics of Basics
make the simple flower/rock drawing game by yourself
```
import pgzrun
import sys # for sys.exit()
HEIGHT = 300
WIDTH = 300
elf = Actor("c1")
flowers = []
def update():
if keyboard.A:
elf.x -= 5
if keyboard.D:
elf.x += 5
if keyboard.W:
elf.y -= 5
if keyboard.S:
elf.y += 5
if keyboard.F:
flower = Actor("flower")
flower.x = elf.x
flower.y = elf.y
flowers.append(flower)
if keyboard.R:
flower = Actor("rock")
flower.x = elf.x
flower.y = elf.y
flowers.append(flower)
if keyboard.Q:
sys.exit(0)
if elf.x < 0:
elf.x = 10
if elf.y < 0:
elf.y = 10
if elf.x > WIDTH:
elf.x = WIDTH - 10
if elf.y > HEIGHT:
elf.y = HEIGHT - 10
def draw():
screen.fill('black')
elf.draw()
for flower in flowers:
flower.draw()
pgzrun.go()
```
[DAY-106] Read/Write File; Lists
Have some fun drawing, add more colors, change the size, enjoy!
```
import pgzrun
import sys # for sys.exit()
HEIGHT = 800
WIDTH = 1000
elf = Actor("c1")
colors = [
[(255,0,0), Rect(0,0,40,40)],
[(0,255,0), Rect(60,0,40,40)],
[(0,0,255), Rect(120,0,40,40)],
[(0,128,128), Rect(180,0,40,40)],
[(0,191,255), Rect(240,0,40,40)],
[(255,215,0), Rect(300,0,40,40)],
]
color = None
pixels = []
size = 40
def make_rect_around_actor(a):
return Rect(a.x,a.y,size,size)
def update():
global color, pixels,size
if keyboard.LEFT:
elf.x -= 2
if keyboard.RIGHT:
elf.x += 2
if keyboard.UP:
elf.y -= 2
if keyboard.DOWN:
elf.y += 2
if keyboard.MINUS:
size -= 1
if size < 1:
size = 1
if keyboard.EQUALS:
size += 1
if keyboard.Q:
sys.exit(0)
if keyboard.SPACE and color != None:
pixels.append([
color,
make_rect_around_actor(elf),
])
if keyboard.C:
pixels = []
color = None
if keyboard.S:
f = open("save.txt", "w")
for p in pixels:
(red,green,blue) = p[0]
f.write(str(red))
f.write(",")
f.write(str(green))
f.write(",")
f.write(str(blue))
f.write(",")
f.write(str(p[1].x))
f.write(",")
f.write(str(p[1].y))
f.write(",")
f.write(str(p[1].width))
f.write(",")
f.write(str(p[1].height))
f.write("\n")
f.close()
if keyboard.L:
pixels = []
f = open("save.txt", "r")
lines = f.readlines()
for l in lines:
(red,green,blue,x,y,w,h) = l.split(",")
pixels.append([
(float(red),float(green),float(blue)),
Rect(float(x),float(y), float(w), float(h))
])
f.close()
if keyboard.k_1:
color = colors[0][0]
if keyboard.k_2:
color = colors[1][0]
if keyboard.k_3:
color = colors[2][0]
if keyboard.k_4:
color = colors[3][0]
if keyboard.k_5:
color = colors[4][0]
if keyboard.k_6:
color = colors[5][0]
if keyboard.D:
drop = make_rect_around_actor(elf)
for p in list(pixels):
if drop.colliderect(p[1]):
pixels.remove(p)
for c in colors:
if elf.colliderect(c[1]):
color = c[0]
def draw():
screen.fill('black')
for c in colors:
screen.draw.filled_rect(c[1], c[0])
for p in pixels:
screen.draw.filled_rect(p[1], p[0])
if color != None:
screen.draw.rect(make_rect_around_actor(elf), color)
elf.draw()
screen.draw.text(str(len(pixels)), topleft=(10,10))
pgzrun.go()
```
[DAY-107] Lists; Dictionaries
count the words in a file
```
f = open("week-015.md","r")
count = []
for line in f.readlines():
for word in line.rstrip().split(" "):
found = False
for counted in count:
if counted[0] == word:
counted[1]+= 1
found = True
break
if not found:
count.append([word, 1])
f.close()
print(count)
```
use a dictionary
```
f = open("week-015.md","r")
count = {}
for line in f.readlines():
for word in line.rstrip().split(" "):
if word in count:
count[word] += 1
else:
count[word] = 1
f.close()
for k in count:
print(count[k], k)
```
get the unique words in a file
```
f = open("week-015.md","r")
unique = set()
for line in f.readlines():
for word in line.rstrip().split(" "):
unique.add(word)
f.close()
print(unique)
```
lets read the file 1 byte at a time:
```
f = open("week-015.md","r")
word = ''
count = {}
while True:
byte = f.read(1)
if not byte:
break
if byte == ' ' or byte == '\n':
if word in count:
count[word] += 1
else:
count[word] = 1
word = ''
else:
word += byte
f.close()
for k in count:
print(count[k], k)
```
use sys.stdin to read the standard input
```
import sys
count = {}
for line in sys.stdin.readlines():
for word in line.rstrip().split(" "):
if word in count:
count[word] += 1
else:
count[word] = 1
for k in count:
print(count[k], k)
``
then try use the output of
catto print the contents of week-015.md and then
|` pipe it to your word counting program
$ cat week-015.md | python3 count.py
if you want to sort by most common words:
cat week-015.md | python3 count.py | sort -n
[DAY-108] Dictionaries
count how many times each character appears in a string
```
line = "A quick brown fox jumps over the lazy dog"
count = {}
for s in line:
if s not in count:
count[s] = 1
else:
count[s] += 1
for s in count:
print(count[s], s)
```
check if all characters from an alphabet are in a string
```
alphabet = {
'a': True,
'b': True,
'c': True,
'd': True,
'e': True,
'f': True,
'g': True,
'h': True,
'i': True,
'j': True,
'k': True,
'l': True,
'm': True,
'n': True,
'o': True,
'p': True,
'q': True,
'r': True,
's': True,
't': True,
'u': True,
'v': True,
'w': True,
'x': True,
'y': True,
'z': True,
' ': True,
}
line = "A quick brown fox jumps over the lazy dog"
for s in line:
lower_case = s.lower()
if lower_case not in alphabet:
print(lower_case + " is not in the alphabet")
break
```
are two strings equal
```
def equal(a,b):
if len(a) != len(b):
return False
for i in range(len(a)):
if a[i] != b[i]:
return False
return True
print(equal("hello","world"))
print(equal("hello","hello"))
print(equal("hello","roblox"))
```
are two lists of integers equal:
```
def equal(a,b):
if len(a) != len(b):
return False
for i in range(len(a)):
if a[i] != b[i]:
return False
return True
print(equal([1,2,3],[1,2,3,4]))
print(equal([1,2,3],[1,2,3]))
```
are two dictionaries equal
```
def equal(a,b):
for k in a:
if k not in b:
return False
if a[k] != b[k]:
return False
for k in b:
if k not in a:
return False
if b[k] != a[k]:
return False
return True
print(equal({'a':'hello','b':'world'},{'a':'hello','b':'world'}))
print(equal({'a':'hello','b':'world'},{'a':'hello','b':'earth'}))
print(equal({'a':'hello','roblox': True},{'a':'hello', 'roblox': False}))
print(equal({'a':'hello','b':'world','roblox': True},{'a':'hello','b':'world'}))
```
[DAY-109] Touch Typing Day
Touchtyping day!
[DAY-110] Find Code on TikTok
follow zippycode on tiktok https://www.tiktok.com/@zippycode
try some of their ideas, like:
from turtle import *
bgcolor('black')
n = 0
colormode(255)
while n < 200:
right(n)
forward(n*3)
color(n,255-n,n%30*8)
n+=1
from turtle import *
color('green')
speed(11)
i = 0
while True:
circle(i*1.5)
right(4)
i+=1
[DAY-111] Lists; Random
```
import pgzrun
import random
WIDTH = 400
HEIGHT = 400
fox = Actor("c1")
fox.x = WIDTH/2
fox.y =HEIGHT/2
other = [
Actor("c2", pos=(100,100)),
Actor("c2", pos=(100,300)),
Actor("c2",pos=(300,300)),
Actor("c2",pos=(300,100))
]
def update():
if keyboard.left:
for o in other:
o.x += 5
if keyboard.right:
for o in other:
o.x -= 5
if keyboard.up:
for o in other:
o.y += 5
if keyboard.down:
for o in other:
o.y -= 5
for o in list(other):
if o.colliderect(fox):
other.remove(o)
if len(other) < 4:
other.append(Actor("c2",pos=(random.randint(10,WIDTH-10), random.randint(10,HEIGHT-10))))
for o in other:
o.y -=1
def draw():
screen.clear()
screen.fill("deepskyblue")
fox.draw()
for o in other:
o.draw()
pgzrun.go()
```
[DAY-112] Use Simple Dictionary
Count the words in a song
```
song = """There once was a ship that put to sea
The name of the ship was the Billy of Tea
The winds blew up, her bow dipped down
O blow, my bully boys, blow (huh)
She had not been two weeks from shore
When down on her a right whale bore
The captain called all hands and swore
He'd take that whale in tow (huh)
Soon may the Wellerman come
To bring us sugar and tea and rum (hey)
One day, when the tonguin' is done
We'll take our leave and go
Take our leave and go
Soon may the Wellerman come
To bring us sugar and tea and rum
One day, when the tonguin' is done
We'll take our leave and go
Before the boat had hit the water
The whale's tail came up and caught her
All hands to the side harpooned and fought her
When she dived down below (huh)
She had not been two weeks from shore
When down on her a right whale bore
The captain called all hands and swore
He'd take that whale in tow (huh)
Soon may the Wellerman come
To bring us sugar and tea and rum (hey)
One day, when the tonguin' is done
We'll take our leave and go
Take our leave and go
Soon may the Wellerman come
To bring us sugar and tea and rum
One day, when the tonguin' is done
We'll take our leave and go
Soon may the Wellerman come
To bring us sugar and tea and rum (hey)
One day, when the tonguin' is done
We'll take our leave and go
Take our leave and go
Take our leave and go
"""
words = {}
word = ''
for c in song:
if c == ' ' or c == '\n':
if word not in words:
words[word] = 1
else:
words[word] += 1
word = ''
else:
word += c
for word in words:
print(words[word],word)
```
This program has a bug, if the file does not end with empty line, it wont count the last word.
Print the length:
...
l = 0
for c in song:
l += 1
print(l)
print(len(song))
[DAY-113] Discover Pythontutor
use https://pythontutor.com/visualize.html with the folloowing code:
```
song = """Soon may the Wellerman come
To bring us sugar and tea and rum (hey)
One day, when the tonguin' is done
We'll take our leave and go
Take our leave and go
Soon may the Wellerman come
To bring us sugar and tea and rum (hey)
One day, when the tonguin' is done
"""
words = {}
word = ''
for c in song:
if c == ' ' or c == '\n':
if word not in words:
words[word] = 1
else:
words[word] += 1
word = ''
else:
word += c
for word in words:
print(words[word],word)
```
try it with other programs as well.
[DAY-114] Simple Turtle
random walk
```
from turtle import *
from random import randint,choice
colors = ['red','deepskyblue','lawngreen']
screen = Screen()
width, height = screen.window_width(), screen.window_height()
pensize(5)
speed(20)
while True:
pencolor(choice(colors))
setheading(randint(0,360))
forward(randint(1,100))
(x,y) = pos()
if x > width/2 or y > height/2 or x < -width/2 or y < -height/2:
setpos(0,0)
```
[DAY-115] Practical Coding, Control Roblox with python
Control Roblox with python
NB: That might be considered cheating, even though its just for fun, so be ready to get your account banned.
First pip install pyautogui
and pip install pydirectinput
.
```
import pyautogui
import pydirectinput
import time
time.sleep(2)
while True:
for key in ['w','a','s','d']:
print('executing',key)
pydirectinput.keyDown(key)
time.sleep(1.6)
pydirectinput.keyUp(key)
time.sleep(0.5)
```
This is a simple program that presses w a s d, each for 1.6 seconds and then waits 0.5 seconds for the next one.
After you start the program, you have 2 seconds to click on Roblox otherwise the sequence will be wrong
[DAY-116] Many Turtles
Many Turtles.
The ideas are borrowed from Redisovering Logo with Bob the Turtle , Ayush Sharma's amazing blog post!
```
import turtle
turtle.setup(width=800, height=800)
bob = turtle.Turtle(shape='turtle')
bob.color('orange')
bob.speed(3000)
alice = turtle.Turtle(shape='turtle')
alice.color('lawngreen')
alice.speed(3000)
for i in range(500):
bob.forward(i)
bob.left(91)
alice.backward(i)
alice.right(91)
turtle.exitonclick()
```
even more turtles
```
import turtle
turtle.setup(width=800, height=800)
bob = turtle.Turtle(shape='turtle')
bob.color('orange')
bob.speed(3000)
alice = turtle.Turtle(shape='turtle')
alice.color('lawngreen')
alice.speed(3000)
charlie = turtle.Turtle(shape='turtle')
charlie.color('deepskyblue')
charlie.speed(3000)
for i in range(500):
bob.forward(i)
bob.left(91)
alice.backward(i)
alice.right(91)
charlie.forward(i)
charlie.right(101)
turtle.exitonclick()
```
```
import turtle
turtle.setup(width=800, height=800)
bob = turtle.Turtle(shape='turtle')
bob.color('orange')
alice = turtle.Turtle(shape='turtle')
alice.color('lawngreen')
angle = 10
while True:
alice.backward(20)
bob.forward(20)
alice.right(angle)
bob.left(angle)
angle += 1
```
Again this is the same as in roblox's houses, you have the blueprint of the house, and you can create an instance of it, and then you can modify it. so turtle.Turtle()
creates an instance, and then you see, bob, alice and charlie have their own changes. In the same time they have the same functionality, like forward
up
and etc coming from the blueprint and each of those methods work on the instance itself.
[DAY-117] Another Text Editor
And lets discuss another text editor.
(if you are on windows make sure you pip3 install windows-curses
)
Start super simple, what do we need to make a text editor? first we need to show the text being edited, and second we need to capture user input and modify this text.
First show some text:
```
import curses
import time
screen = curses.initscr()
screen.addstr(0, 0, "hello world",curses.A_NORMAL)
screen.refresh()
time.sleep(2)
```
Capture input and modify the text:
```
import curses
screen = curses.initscr()
text = ''
while True:
screen.addstr(0, 0, text,curses.A_NORMAL)
screen.refresh()
c = screen.getch()
text += chr(c)
```
In order to Read and Write the file we are editing, we need to have some control keys, like Ctrl+S to save, and Ctrl+C to quit without saving. Also we need to add support for backspace to be able to delete from the text string.
Hint: use text += str(c)
to actually see the codes you need.
```
import curses
import sys
screen = curses.initscr()
curses.curs_set(2)
if len(sys.argv) != 2:
print("usage:")
print(sys.argv[0] + " filename")
sys.exit(1)
text = ''
try:
file = open(sys.argv[1],"r")
text = file.read()
file.close()
except:
pass
status = 'file: ' + sys.argv[1]
while True:
screen.clear()
screen.addstr(0, 0, status + ' (len: ' + str(len(text)) + ')',curses.A_NORMAL)
screen.addstr(2, 0, text,curses.A_NORMAL)
screen.refresh()
c = screen.getch()
if c == 3:
# quit Ctrl+C
break
if c == 19:
# save Ctrl+S
file = open(sys.argv[1],"w")
file.write(text)
file.close()
status = 'file: ' + sys.argv[1]
screen.addstr(0, 0, text,curses.A_NORMAL)
continue
if c == 8:
# backspace
if len(text) > 0:
text = text[:len(text)-1]
continue
if (c < 127 and c > 30) or c == 10:
text += chr(c)
status = 'file: ' + sys.argv[1] + " (modified)"
```
[DAY-118] Search Lyrics
Search for your favorite lyrics, dont forget to pip3 install lyricsgenius
import lyricsgenius
genius = lyricsgenius.Genius('get api key from genius.com')
genius.verbose = False
while True:
artist = input("🔥 Artist: ")
song_name = input("🔥 Song: ")
song = genius.search_song(song_name, artist)
if song == None:
print(song_name + " / " + artist + " not found")
else:
print('-' * 40)
print(song.lyrics)
print('-' * 40)
[DAY-119] Facial Recognition; Move 78
Use https://github.com/ageitgey/face_recognition to see how easy it is to track people through a video stream only using 1 picture from them.
Recognize that if it is cheap and easy, it is done to you.
It will be done in the mall, to show you personalized ads, it will be done on the street to track where you go so they can sell you better things on tiktok.
They only need 1 picture.
If you are not paying, you are the product.
It is also not very easy to be tricked with mascara.
even thought it was easy in 2014, https://www.theatlantic.com/technology/archive/2014/07/makeup/374929/
[DAY-120] Program on your own form a book
Today you are on your own. We start with: https://www.amazon.de/-/en/DK/dp/1465461884 chapter 2, read it for 1 hour and make the programs and exercieses.
Write down your experience and what you struggle with.
Simple ping pong game
```
import pgzrun
import random
HEIGHT = 600
WIDTH = 600
elf = Actor('c1')
king = Actor('c2')
ball = Actor('bullet')
king.y = HEIGHT/2
elf.y = HEIGHT/2
elf.x = WIDTH-10
ball.x = WIDTH/2
ball.y = HEIGHT/2
d = 1
game_over = False
speed = 1
def update():
global d,game_over,speed
if keyboard.up:
elf.y -= 5
if keyboard.down:
elf.y += 5
if keyboard.S:
king.y += 5
if keyboard.W:
king.y -= 5
if ball.x < 0 or ball.x > WIDTH:
game_over = True
if d == 1:
ball.x += speed
else:
ball.x -= speed
if elf.colliderect(ball):
d = 0
ball.y = random.randint(10,HEIGHT-10)
speed += 1
if king.colliderect(ball):
d = 1
ball.y = random.randint(10,HEIGHT-10)
speed += 1
def draw():
screen.clear()
screen.fill("deepskyblue")
elf.draw()
king.draw()
ball.draw()
if game_over:
screen.fill('red')
pgzrun.go()
```
[DAY-121] Scam Check List
Scams.. Scams everywhere.
Our phone numbers, names, address are everywhere we have registered to buy something, be it bol.com, amazon, some random website we bought fidgets from, etc. So people can find out your number and name also by stealing your friends's contact list, Overall you must assume the bad guys have your information, so when you receive a call or email or even people talk to you on the street, always think sus.
Follow this list:
Always Think Sus
Call your parents
If you cant reach your parents, call adult you know
If you cant reach adult you know, go and find a mother with a child, they are the safest to talk to.
If you can not find any adult to help hang up.
If you think it is serious and you must act, hang up, and you call wherever they claim to be calling from. For example if they say they are from your bank, or from roblox, or fortnite, you google and find a contact for your bank/fortnite and you call them and ask what is going on.
The scammers are very smart, and have a lot of experience to trick you into doing what they want, sometimes they will call claiming your parents are in trouble and you have to give them a credit card number, sometimes they will call to tell you you win the new iPhone if you just give them a credit card number. They are very inventive as well, so the best thing is just think sus.
[DAY-122] Lists; Random; Mutate
Hide and Seek
Ask someone to count to 10, then you hide, and ask him to find you
```
import pgzrun
import random
HEIGHT = 600
WIDTH = 600
elf = Actor('c1')
elf.x = 20
elf.y = random.randint(0,HEIGHT)
def update():
if keyboard.UP:
elf.y -= 5
if keyboard.DOWN:
elf.y += 5
if keyboard.RIGHT:
elf.x += 5
if keyboard.LEFT:
elf.x -= 5
def draw():
elf.draw()
pgzrun.go()
```
Practice walking over a list with for i in range(len(x))
and for item in x
.
```
import pgzrun
import random
HEIGHT = 600
WIDTH = 600
elf = Actor('c1')
king = Actor('c2')
elf.x = 20
elf.y = random.randint(0,HEIGHT)
king.y = random.randint(0,HEIGHT)
king.x = WIDTH-20
things = []
def add_new_obsticle(l):
image = random.choice(["snake","bullet","flower","rock"])
x = Actor(image)
x.x = random.randint(0,WIDTH)
x.y = random.randint(0,HEIGHT)
l.append(x)
for i in range(10):
add_new_obsticle(things)
def update():
if keyboard.UP:
elf.y -= 5
if keyboard.DOWN:
elf.y += 5
if keyboard.RIGHT:
elf.x += 5
if keyboard.LEFT:
elf.x -= 5
if keyboard.W:
king.y -= 5
if keyboard.S:
king.y += 5
if keyboard.D:
king.x += 5
if keyboard.A:
king.x -= 5
for s in range(len(things)):
if things[s].colliderect(elf):
elf.image = things[s].image
if king.colliderect(elf):
king.image = "c3"
def draw():
screen.fill('azure')
king.draw()
elf.draw()
for thing in things:
thing.draw()
pgzrun.go()
```
[DAY-123] Lists; Callbacks
a bit more complicated game
```
import pgzrun
import random
from itertools import cycle
WIDTH = 300
HEIGHT = 300
game_over = False
player = Actor("c1", pos=((WIDTH/2), (HEIGHT-16)), anchor=("center","bottom"))
obsticles = []
def jump_up(jumper):
sounds.jump.play()
animate(jumper, tween='decelerate', duration=0.3, pos=(jumper.x, jumper.y - 16),on_finished=lambda: jump_down(jumper))
def jump_down(jumper):
animate(jumper, tween='accelerate', duration=0.3, pos=(jumper.x, HEIGHT-16))
def on_key_down(key):
if key == keys.SPACE:
jump_up(player)
def make_obsticles():
for i in range(0, 5 - len(obsticles)):
# check if colliding, add random + 20 to it
actor = Actor(random.choice(["o1","o2","o3","o4","o5","o6","o7","o8","o9","o10","o11"]), anchor=("center","bottom"))
actor.x = WIDTH + 40 + random.randint(10, WIDTH*2)
actor.y = HEIGHT - 16
while True:
actor.x += random.randint(30, 50)
conflict = False
for o in obsticles:
if o.colliderect(actor):
conflict = True
if not conflict:
break
obsticles.append(actor)
def update():
global game_over
if len(obsticles) < 5:
make_obsticles()
for o in list(obsticles):
# shrink the collision rects so the game is more fun to play
if o.inflate(-4,-4).colliderect(player.inflate(-16,-16)):
game_over = True
# remove the obsticles out of screen
o.x -= 2
if o.x < -10:
obsticles.remove(o)
player animation
we just change the image of the actor every 0.4 seconds
poses = cycle(["player/tiles-46","player/tiles-47","player/tiles-48","player/tiles-49","player/tiles-50","player/tiles-51"])
def make_actor_move():
player.image = next(poses)
clock.schedule_interval(make_actor_move, 0.4)
def draw():
screen.fill("black")
player.draw()
for o in obsticles:
o.draw()
for i in range(100):
screen.blit('floor',(i * 16, HEIGHT - 16))
if game_over:
screen.fill("red")
pgzrun.go()
```
[DAY-124] BMP format, Images; Encoding/Decoding
Images
The way we store image is very similar to the way we store text. It is just a bunch of bytes, but when we read them we decide to interpret them differently.
Open images/joshi-100.bmp and you will see:
Now lets just read the bytes, and just show the numbers, starting at position 54, when we print new line every 106, and also we are gonna print every 4th byte.
first just print the bytes:
```
file = open("images/joshi-100.bmp","rb")
data = file.read()
file.close()
for b in data:
print("%3d" % b,end='')
```
now lets print them in specific order:
```
file = open("images/joshi-100.bmp","rb")
data = file.read()
file.close()
width = 100
height = 106
offset = 54
for y in range(width):
for x in range(height):
off = offset + ((y * width + x) * 4)
print("%3d" % data[off+2],end='')
print()
```
looks familiar!
The image itself actually contains information about how big it is, and where the data starts, it is specified in the bitmap format itself.
Here is the bitmap header information, copied from: http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/2003_w/misc/bmp_file_format/bmp_file_format.htm
| Name | Size | Offset | Description |
| - | - | - | - |
| Header | 14 bytes | | Windows Structure: BITMAPFILEHEADER |
| Signature | 2 bytes | 0000h | 'BM' |
| FileSize | 4 bytes | 0002h | File size in bytes |
| reserved | 4 bytes | 0006h | unused (=0) |
| DataOffset | 4 bytes | 000Ah | Offset from beginning of file to the beginning of the bitmap data |
| InfoHeader | 40 bytes | | Windows Structure: BITMAPINFOHEADER |
| Size | 4 bytes | 000Eh | Size of InfoHeader =40 |
| Width | 4 bytes | 0012h | Horizontal width of bitmap in pixels |
| Height | 4 bytes | 0016h | Vertical height of bitmap in pixels |
| Planes | 2 bytes | 001Ah | Number of Planes (=1) |
| Bits Per Pixel | 2 bytes | 001Ch | Bits per Pixel used to store palette entry information. This also identifies in an indirect way the number of possible colors. Possible values are: 1 = monochrome palette. NumColors = 1 4 = 4bit palletized. NumColors = 16 8 = 8bit palletized. NumColors = 256 16 = 16bit RGB. NumColors = 65536 24 = 24bit RGB. NumColors = 16M |
| Compression | 4 bytes | 001Eh | Type of Compression 0 = BI_RGB no compression 1 = BI_RLE8 8bit RLE encoding 2 = BI_RLE4 4bit RLE encoding |
| ImageSize | 4 bytes | 0022h | (compressed) Size of Image It is valid to set this =0 if Compression = 0 |
| XpixelsPerM | 4 bytes | 0026h | horizontal resolution: Pixels/meter |
| YpixelsPerM | 4 bytes | 002Ah | vertical resolution: Pixels/meter |
| Colors Used | 4 bytes | 002Eh | Number of actually used colors. For a 8-bit / pixel bitmap this will be 100h or 256. |
| Important Colors | 4 bytes | 0032h | Number of important colors 0 = all |
| ColorTable | 4 * NumColors bytes | 0036h | present only if Info.BitsPerPixel less than 8 colors should be ordered by importance |
| Red | 1 byte | | Red intensity |
| Green | 1 byte | | Green intensity |
| Blue | 1 byte | | Blue intensity |
| reserved | 1 byte | | unused (=0) |
| repeated NumColors times |
| Pixel Data | InfoHeader.ImageSize bytes | | The image data
Now using the header information, we can get the width, height and data offset directly from there:
```
file = open("images/joshi-100.bmp","rb")
data = file.read()
file.close()
offset = int.from_bytes(data[10:14], byteorder='little')
width = int.from_bytes(data[18:22], byteorder='little')
height = int.from_bytes(data[22:26], byteorder='little')
for y in range(width):
for x in range(height):
off = offset + ((y * width + x) * 4)
print("%3d" % data[off+2],end='')
print()
```
You see when we read data[10:14]
we want to skip signature
(2 bytes), file size
(4 bytes) and reserved
(4 bytes) and read exactly 4 bytes after that.
And we can make 4 bytes into a integer with int.from_bytes
. We will get into that later. For now the important thing to focus on is the format itself.
It has a header, followed up by data. This is very common method and you will see it in all kinds of places. Even in our virtual computer when we were storing the strings we used a similar method, the first byte was always the length of the string.
[DAY-125] Lists; Dictionaries
Write code to destroy your enemies!
You have access to your heroes
and enemies
positions. When you collide you destroy each other.
```
import pgzrun
import random
from itertools import cycle
WIDTH=600
HEIGHT=600
enemies = []
heroes = []
text = """
for h in heroes:
h.x += random.randint(-10,10)
h.y += random.randint(-10,10)
"""
enemy_programs = cycle([
"""
i = 0
for e in enemies:
e.x = i * 10
e.y = i * 10
i += 1
""",
"""
for e in enemies:
e.x += random.randint(-10,10)
e.y += random.randint(-10,10)
""",
"""
for e in enemies:
(x,y) = random.choice(heroes)
e.x = x
e.y = y
"""
])
enemy_code = None
def reset():
global heroes, enemies, enemy_code
enemy_code = next(enemy_programs)
enemies = []
heroes = []
for i in range(20):
enemies.append(Rect(random.randint(0,WIDTH),random.randint(0,HEIGHT), 10, 10))
heroes.append(Rect(random.randint(0,WIDTH),random.randint(0,HEIGHT), 10, 10))
def on_key_down(key, mod, unicode):
global text, pause, score_words, score
if key == keys.BACKSPACE:
if mod == 1024 or mod == 256:
text = ''
if len(text) > 0:
text = text[:-1]
elif key == keys.SPACE:
text += ' '
elif key == keys.TAB:
text += ' '
elif key == keys.RETURN:
text += '\n'
elif len(unicode) > 0 and ord(unicode) >= 34 and ord(unicode) <= 126:
text += unicode
def run_code():
try:
enemy_positions = []
for e in enemies:
enemy_positions.append((e.x, e.y))
hero_positions = []
for h in heroes:
hero_positions.append((e.x, e.y))
exec(text, {"heroes": heroes,"random":random, "enemies": enemy_positions})
exec(enemy_code, {"enemies": enemies, "random":random, "heroes": hero_positions})
for h in list(heroes):
collided = False
for e in list(enemies):
if e.colliderect(h):
enemies.remove(e)
if collided:
heroes.remove(h)
if len(enemies) < 50:
enemies.append(Rect(random.randint(0,WIDTH),random.randint(0,HEIGHT), 10, 10))
heroes.append(Rect(random.randint(0,WIDTH),random.randint(0,HEIGHT), 10, 10))
if len(enemies) < 5:
reset()
except Exception as err:
print(err)
pass
reset()
clock.schedule_interval(run_code, 1)
def draw():
screen.fill("black")
screen.draw.text("heroes: " + str(len(heroes)) + " enemies: " + str(len(enemies)), (0, 0), align='left',fontname="437-win", fontsize=20)
for (i,l) in enumerate(enemy_code.split('\n')):
screen.draw.text(l, (0, (20 + (i * 16))), align='left',fontname="437-win", fontsize=14)
for (i,l) in enumerate(text.split('\n')):
screen.draw.text(l, (0, (HEIGHT - 200 + (i * 16))), align='left',fontname="437-win", fontsize=14)
for e in enemies:
screen.draw.rect(e, (255,0,0))
for h in heroes:
screen.draw.rect(h, (0,255,255))
pgzrun.go()
```
[DAY-126] Read/Write File
Save and load the position of the elf
Play hide and seek after that!
```
import pgzrun
HEIGHT = 600
WIDTH = 600
elf = Actor('c1')
elf.x = WIDTH/2
elf.y = HEIGHT/2
def update():
if keyboard.UP:
elf.y -= 5
if keyboard.LEFT:
elf.x -= 5
if keyboard.RIGHT:
elf.x += 5
if keyboard.DOWN:
elf.y += 5
if keyboard.S:
f = open('save','w')
f.write('MAGIC HEADER\n' + str(elf.x) + '\n' + str(elf.y) + '\n')
f.close()
if keyboard.B:
f = open("save","r")
lines = f.readlines()
if (lines[0].startswith('MAGIC HEADER')):
elf.x = float(lines[1])
elf.y = float(lines[2])
f.close()
def draw():
elf.draw()
pgzrun.go()
```
[DAY-127] Callbacks; Schedule Interval
super short, make the actor walk
```
from itertools import cycle
import pgzrun
WIDTH=200
HEIGHT=200
elf = Actor("c1")
elf.x = WIDTH/2
elf.y = HEIGHT/2
poses = cycle(["player/tiles-46","player/tiles-47","player/tiles-48","player/tiles-49","player/tiles-50","player/tiles-51"])
def make_actor_move():
elf.image = next(poses)
clock.schedule_interval(make_actor_move, 0.4)
def draw():
screen.fill("black")
elf.draw()
pgzrun.go()
```
[DAY-128] Lists; CPU usage; Resources
See how slow you can make your computer, by making it draw 100 000 actors 60 times per second.
See how slow it moves, open the activity monitor or the task manager to see how it eats all your resources.
After that chabnge it to 100 actors and see the difference.
```
import random
import pgzrun
WIDTH = 800
HEIGHT = 800
actors = []
for i in range(0, 100000):
elf = Actor("c1")
elf.x = WIDTH/2
elf.y = HEIGHT/2
actors.append(elf)
def update():
if keyboard.UP:
for i in range(0, len(actors)):
a = actors[i]
a.y -= i
if keyboard.DOWN:
for i in range(0, len(actors)):
a = actors[i]
a.y += i
if keyboard.LEFT:
for i in range(0, len(actors)):
a = actors[i]
a.x -= i
if keyboard.RIGHT:
for i in range(0, len(actors)):
a = actors[i]
a.x += i
def draw():
screen.fill("black")
for a in actors:
a.draw()
pgzrun.go()
```
[DAY-129] Eat your computer; Memory; CPU
consume one CPU on your computer
while True:
x = 1
Open activity monitor/task manager and see how it will consume 100% of one CPU, your computer has more than one CPU, this code will totally consume one, and in a bit you will see the computer will get hot, and the fans will start spinning. This is because each cycle of the CPU requires energy. So when you consume 100% of the CPU it will consume the maximum possible energy, and every time you use energy something is lost, and the loss is radiated as heat, even when you run, and you sweat you can see heat coming out of you.
It might seem like x = 1
is doing nothing, but it actually has to go to the memory address of the variable x and set it to value 1
Now, lets consume all the memory.
a = []
for i in range(10000000000):
a.append(i)
This will create a list with 10000000000 items in it, in python the size of an integer is a bit bigger than you think, usually numbers are stored in 4 byte or 8 byte memory slots; so 10000000000 * 4 is approximately 40 gigabytes of memory, your computer has 16 or 32 gigabytes. If you let the program run long enough you will see how it grows, and it consumes more and more memory.
Now you might be surprised when it reaches your computer's max memory and it keeps going, and this is because your operating system will start taking memory out and writing it to your hard disk, this is called swapping. You will see your swap grow. If you wait long enough your computer will become slower and slower, and at some point it will be unusable.
[DAY-130] turtle; lists; classes
many turtles
```
import turtle
import random
colors = ['violet', 'turquoise', 'black',
'deepskyblue','lawngreen', 'seagreen ',
'royalblue', 'purple', 'red','orange']
turtles = []
for i in range(10):
t = turtle.Turtle()
t.color(random.choice(colors))
t.speed(9000)
turtles.append(t)
while True:
for i in range(len(turtles)):
t = turtles[i]
t.setheading(random.randint(0,360))
t.forward(10)
```
Lets practice making a new class, you see when we say Turtle() or Actor() we make a new instance of the class Turtle and the class Actor
The Class itself is like a blueprint of how to make a new instance of itself, for example lets make a class Point that has two properties, x
and y
```
class Point:
x = 0
y = 0
points = []
for i in range(10):
p = Point()
p.x = i * 20
p.y = i * 20
points.append(p)
for p in points:
print(p, p.x, p.y)
```
When you define a function in a class, you have access to special parameter, self
which is the instance on which this function is called:
```
class Dog:
name = ''
def bark(self):
print(self.name+' woof woof woof')
max = Dog()
max.name = 'Maxie'
max.bark()
rocky = Dog()
rocky.name = "Rocky"
rocky.bark()
```
There is also a special __init__
function, called constructor that lets you pass parameters directly when you create the instance.
```
class Point:
x = 0
y = 0
def __init__(self, x,y):
self.x = x
self.y = y
points = []
for i in range(10):
p = Point(i * 10, i * 20)
points.append(p)
for p in points:
print(p, p.x, p.y)
```
[DAY-131] Lists; Files; Dictionaries
Example dictionary, List and String
```
words = {}
words["some long key"] = True
words["x"] = 10
for k in words:
print(k)
print(words[k])
list_of_characters = ['a','b','c']
for i in range(len(list_of_characters)):
print(i)
print(list_of_characters[i])
s = "hello"
for i in range(len(s)):
print(i)
print(s[i])
```
You see how in the list and string we can address individual element or character by its index? In the dictionary we address things by their key, for example if i want to see the value of some long key
I do print(words["some long key"])
.
Now unrelated, but lets practice printing the first 100 numbers from a list.
```
a = []
for i in range(100):
a.append(i)
for i in range(100):
print(a[i])
```
Append to file, whatever command line agurments 1 and 2 are
```
import sys
f = open("account.txt", "a")
f.write(sys.argv[1] + " " + sys.argv[2] + "\n")
f.close()
```
[DAY-132] Lists; Classes
a tower defense game
```
import pgzrun
import random
WIDTH=1024
HEIGHT=576
towers = []
enemies = []
bullets = []
game_over = False
background = Actor("grass_template2", pos=(0,0), anchor=(0,0))
player = Actor("c1", pos=(WIDTH/2, HEIGHT/2), anchor=('center','bottom'))
lives = 100
cash = 100
current_wave = 1
class Tower:
def init (self, image, x,y, size):
self.actor = Actor(image, pos=(x,y), )
self.rect = Rect((x-size/2,y-size/2), (size,size))
self.color = (random.randint(100,250),random.randint(100,250),random.randint(100,250))
def shoot(self):
for e in enemies:
if e.colliderect(self.rect):
b = Actor("bullet3")
b.x = self.actor.x
b.y = self.actor.y
b.hit = False
animate(b, pos=(e.x,e.y), tween='accelerate', on_finished=lambda: bullets.remove(b))
bullets.append(b)
break
def colliderect(self,other):
return self.actor.colliderect(other)
def draw(self):
self.actor.draw()
#screen.draw.rect(self.rect,self.color)
def shoot():
global cash
for t in towers:
t.shoot()
for e in list(enemies):
if e.image == 'exploded':
enemies.remove(e)
cash+=1
def new_wave():
global current_wave
for i in range(current_wave * 10):
e = Actor("c3")
e.y = HEIGHT
e.x = random.randint(int(WIDTH/3), int(WIDTH-WIDTH/3))
enemies.append(e)
current_wave += 1
def on_key_down(key):
global cash
if key == keys.K_1:
if cash >= 10:
conflict = False
for t in towers:
if t.colliderect(player):
conflict = True
if not conflict:
t = Tower("tower_grass",player.x, player.y, 150)
towers.append(t)
cash -= 10
def update():
global game_over
if keyboard.UP:
player.y -= 5
if keyboard.DOWN:
player.y += 5
if keyboard.LEFT:
player.x -= 5
if keyboard.RIGHT:
player.x += 5
for e in enemies:
if e.image != 'exploded':
e.y -= random.randint(-1,2)
for b in bullets:
if b.colliderect(e):
e.image = 'exploded'
b.hit = True
break
if not background.colliderect(e):
game_over = True
pass
clock.schedule_interval(shoot, 1)
clock.schedule_interval(new_wave, 10)
new_wave()
def draw():
screen.clear()
if game_over:
screen.fill('blue')
else:
background.draw()
screen.draw.text("current_wave: " + str(current_wave) + ", cash: " + str(cash) + ", lives: " + str(lives), (5,0),fontname="437-win")
for b in bullets:
if not b.hit:
b.draw()
for e in enemies:
e.draw()
for t in towers:
t.draw()
player.draw()
pgzrun.go()
```
[DAY-133] Touch Typing; Lists
Spend 15 minutes touch typing.
Add a path for the enemies to walk on.
The most important part is to think about, how would you follow a path, in this example we will follow a path by picking a next element to walk towards.
This is the most important part of the change, it is an what is called an algorithm, it is a sequence of steps to solve a problem. We can describe it in words: find the current square you are colliding it, find which square is next in the list, start walking towards it . Now lets write it down:
```
[...]
path = [
Rect(0, HEIGHT/2, 50, 50),
Rect(50, HEIGHT/2, 50, 50),
[...]
def update():
[...]
for e in enemies:
if e.image != 'exploded':
destination = None
for (i, p) in enumerate(path):
if e.colliderect(p) and i < len(path) - 1:
destination = path[i+1]
break
if destination != None:
center_x = destination.x + 25
center_y = destination.y + 25
if e.x < center_x:
e.x += random.randint(0, 2)
if e.x > center_x:
e.x -= random.randint(0, 2)
if e.y > center_y:
e.y -= random.randint(0, 2)
if e.y < center_y:
e.y += random.randint(0, 2)
[...]
```
```
import pgzrun
import random
WIDTH = 1024
HEIGHT = 576
towers = []
enemies = []
bullets = []
game_over = False
background = Actor("grass_template2", pos=(0, 0), anchor=(0, 0))
path_size = 50
path = [
Rect(0, HEIGHT/2, 50, 50),
Rect(50, HEIGHT/2, 50, 50),
Rect(50, HEIGHT/2 + 50, 50, 50),
Rect(100, HEIGHT/2 + 50, 50, 50),
Rect(150, HEIGHT/2 + 50, 50, 50),
Rect(200, HEIGHT/2 + 50, 50, 50),
Rect(250, HEIGHT/2 + 50, 50, 50),
Rect(250, HEIGHT/2 + 100, 50, 50),
Rect(300, HEIGHT/2 + 100, 50, 50),
Rect(350, HEIGHT/2 + 100, 50, 50),
Rect(400, HEIGHT/2 + 100, 50, 50),
Rect(450, HEIGHT/2 + 100, 50, 50),
Rect(500, HEIGHT/2 + 100, 50, 50),
Rect(500, HEIGHT/2 + 150, 50, 50),
Rect(550, HEIGHT/2 + 150, 50, 50),
Rect(600, HEIGHT/2 + 150, 50, 50),
Rect(650, HEIGHT/2 + 150, 50, 50),
Rect(650, HEIGHT/2 + 200, 50, 50),
Rect(700, HEIGHT/2 + 200, 50, 50),
Rect(750, HEIGHT/2 + 200, 50, 50),
Rect(800, HEIGHT/2 + 200, 50, 50),
Rect(850, HEIGHT/2 + 200, 50, 50),
Rect(850, HEIGHT/2 + 150, 50, 50),
Rect(850, HEIGHT/2 + 100, 50, 50),
Rect(850, HEIGHT/2 + 50, 50, 50),
Rect(850, HEIGHT/2 + 0, 50, 50),
Rect(850, HEIGHT/2 - 50, 50, 50),
Rect(850, HEIGHT/2 - 100, 50, 50),
Rect(900, HEIGHT/2 - 100, 50, 50),
Rect(950, HEIGHT/2 - 100, 50, 50),
Rect(1000, HEIGHT/2 - 100, 50, 50),
Rect(1050, HEIGHT/2 - 100, 50, 50),
Rect(1100, HEIGHT/2 - 100, 50, 50),
]
player = Actor("c1", pos=(WIDTH/2, HEIGHT/2), anchor=('center', 'bottom'))
lives = 100
cash = 100
current_wave = 1
class Tower:
def init (self, image, x, y, size):
self.actor = Actor(image, pos=(x, y), )
self.rect = Rect((x-size/2, y-size/2), (size, size))
self.color = (random.randint(100, 250), random.randint(
100, 250), random.randint(100, 250))
def shoot(self):
for e in enemies:
if e.colliderect(self.rect):
b = Actor("bullet3")
b.x = self.actor.x
b.y = self.actor.y
b.hit = False
animate(b, pos=(e.x, e.y), tween='accelerate',
on_finished=lambda: bullets.remove(b))
bullets.append(b)
break
def colliderect(self, other):
return self.actor.colliderect(other)
def draw(self):
self.actor.draw()
screen.draw.rect(self.rect,self.color)
def shoot():
global cash
for t in towers:
t.shoot()
for e in list(enemies):
if e.image == 'exploded':
enemies.remove(e)
cash += 1
def new_wave():
global current_wave
for i in range(10 + (current_wave * 2)):
e = Actor("c3")
e.y = HEIGHT/2+10
e.x = 0
enemies.append(e)
current_wave += 1
def on_key_down(key):
global cash
if key == keys.K_1:
if cash >= 10:
conflict = False
for t in towers:
if t.colliderect(player):
conflict = True
for p in path:
if player.colliderect(p):
conflict = True
if not conflict:
t = Tower("tower_grass", player.x, player.y, 150)
towers.append(t)
cash -= 10
def update():
global game_over
if keyboard.UP:
player.y -= 5
if keyboard.DOWN:
player.y += 5
if keyboard.LEFT:
player.x -= 5
if keyboard.RIGHT:
player.x += 5
for e in enemies:
if e.image != 'exploded':
destination = None
for (i, p) in enumerate(path):
if e.colliderect(p) and i < len(path) - 1:
destination = path[i+1]
break
if destination != None:
center_x = destination.x + 25
center_y = destination.y + 25
if e.x < center_x:
e.x += random.randint(0, 2)
if e.x > center_x:
e.x -= random.randint(0, 2)
if e.y > center_y:
e.y -= random.randint(0, 2)
if e.y < center_y:
e.y += random.randint(0, 2)
for b in bullets:
if b.colliderect(e):
e.image = 'exploded'
b.hit = True
break
if not background.colliderect(e):
game_over = True
pass
clock.schedule_interval(shoot, 1)
clock.schedule_interval(new_wave, 10)
new_wave()
def draw():
screen.clear()
if game_over:
screen.fill('blue')
else:
background.draw()
screen.draw.text("current_wave: " + str(current_wave) + ", cash: " +
str(cash) + ", lives: " + str(lives), (5, 0), fontname="437-win")
for i in range(len(path)):
p = path[i]
screen.draw.filled_rect(p,(255,0,0))
screen.draw.text(str(p.x), (p.x,p.y))
for b in bullets:
if not b.hit:
b.draw()
for e in enemies:
e.draw()
for t in towers:
t.draw()
player.draw()
pgzrun.go()
```
[DAY-134] Lists; Methods
Upgrade our tower game, make it possible to:
delete towers and get some money back
be able to upgrade the tower's range
First we will store original x
,y
and size
in the tower's instance, and then use it to increase its range.
Again pay attention when deleting from a list we are walking on (iterating on), we actually make a clone of the list and iterate over the clone, but remove items from the original list by value.
```
[...]
class Tower:
[...]
def init (self, image, x, y, size):
self.size = size
self.x = x
self.y = y
self.actor = Actor(image, pos=(x, y))
self.rect = Rect((x-size/2, y-size/2), (size, size))
self.color = (random.randint(100, 250), random.randint(100, 250), random.randint(100, 250))
def resize(self, bump):
new_size = self.size + bump
self.size = new_size
self.rect = Rect((self.x-new_size/2, self.y-new_size/2), (new_size, new_size))
[...]
def on_key_down(key):
global cash
if key == keys.K_2:
for t in towers:
if t.colliderect(player):
t.resize(5)
cash -= 10
if key == keys.D:
for t in list(towers):
if t.colliderect(player):
cash += 15
towers.remove(t)
[...]
```
[DAY-134] If
Relax day.
Make super simple game to draw with two players, because we dont clear the screen.
```
import pgzrun
HEIGHT = 800
WIDTH = 800
elf = Actor('c1')
king = Actor('c2')
def update():
if keyboard.W:
elf.y -= 5
if keyboard.S:
elf.y += 5
if keyboard.A:
elf.x -= 5
if keyboard.D:
elf.x += 5
if keyboard.UP:
king.y -= 5
if keyboard.DOWN:
king.y += 5
if keyboard.LEFT:
king.x -= 5
if keyboard.RIGHT:
king.x += 5
def draw():
elf.draw()
king.draw()
pgzrun.go()
```
[DAY-135] Dictionary; For
game-135
Make a morse code machine!
```
import pgzrun
import time
short = tone.create('A3', 0.3)
long = tone.create('D3', 0.7)
morse = {
'a': [short, long],
'b': [long, short, short, short],
'c': [long, short, long, short],
'd': [long, short, short],
'e': [short],
'f': [short, short, long, short],
'g': [long, long, short],
'h': [short, short, short, short],
'i': [short, short],
'j': [short, long, long, long],
'k': [long, short, long],
'l': [short, long, short, short],
'm': [long, long],
'n': [long, short],
'o': [long, long, long],
'p': [short, long, long, short],
'q': [long, long, short, long],
'r': [short, long, short],
's': [short, short, short],
't': [long],
'u': [short, short, long],
'v': [short, short, short, long],
'w': [short, long, long],
'x': [long, short, short, long],
'y': [long, short, long, long],
'z': [long, long, short, short]
}
def play(key):
for t in morse[key]:
t.play()
time.sleep(1)
time.sleep(1)
def on_key_down(key):
if key == keys.A:
play('a')
if key == keys.B:
play('b')
if key == keys.C:
play('c')
if key == keys.D:
play('d')
if key == keys.E:
play('e')
if key == keys.F:
play('f')
if key == keys.G:
play('g')
if key == keys.H:
play('h')
if key == keys.I:
play('i')
if key == keys.J:
play('j')
if key == keys.K:
play('k')
if key == keys.L:
play('l')
if key == keys.M:
play('m')
if key == keys.N:
play('n')
if key == keys.O:
play('o')
if key == keys.P:
play('p')
if key == keys.Q:
play('q')
if key == keys.R:
play('r')
if key == keys.S:
play('s')
if key == keys.T:
play('t')
if key == keys.U:
play('u')
if key == keys.V:
play('v')
if key == keys.W:
play('w')
if key == keys.X:
play('x')
if key == keys.Y:
play('y')
if key == keys.Z:
play('z')
def update():
pass
def draw():
pass
pgzrun.go()
```
[DAY-136] For; Arrays; Memory
Lets make a super simple C program
Just to get familiar witht he syntax, it does not use indentation to group code, but {}, and also each variable has to have known type (size), e.g we have to tell the C compiler (compiler is a program that takes the text code and transforms it into machine code) that i
is of type int
which on our computer is exactly 4 bytes long.
```
include
int main() {
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += 10;
}
printf("%d\n", sum);
}
```
When you execute gcc -o foo foo.c
(if you save the program in foo.c), it will make the binary foo
, do cat foo
to see the actual binary made from the compiler. If you run objdump -D foo
you will see the assembly code and the machine code corresponding to it.
cat foo
:
```
????X? H__PAGEZERO?__TEXT@@__text__TEXT0?X0??__stubs__TEXT????__stub_helper__TEXT?????__cstring__TEXT????__unwind_info__TEXT??H???__DATA_CONST@@@@__got__DATA_CONST@?__DATA?@?@__la_symbol_ptr__DATA?__data__DA?H__LINKEDIT?@?"?? ?0?0h???H
P??
/usr/lib/dyld9??
f:^?[c?υ02
?*(?0?
8d
/usr/lib/libSystem.B.dylib&`)h?UH??H???E??E??E??}?d??E???
?E??E???E???????u?H?=2?? ?E?H??]??%r@L?q@AS?%a?h?????%d
0?44??4
??#Q@dyld_stub_binderQr?s@_printf?__mh_execute_header!main%?~??0?$ __mh_execute_header_main_printfdyld_stub_binder__dyld_privat
```
Because its a binary file, most of the bytes are not actually printable ASCII characters, you can use hexdump
to see the byte's values:
hexdump -C foo
```
00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
00000010 10 00 00 00 58 05 00 00 85 00 20 00 00 00 00 00 |....X..... .....|
00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
00000040 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 19 00 00 00 d8 01 00 00 |................|
00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000080 00 00 00 00 01 00 00 00 00 40 00 00 00 00 00 00 |.........@......|
00000090 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 |.........@......|
000000a0 05 00 00 00 05 00 00 00 05 00 00 00 00 00 00 00 |................|
000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
000000d0 30 3f 00 00 01 00 00 00 58 00 00 00 00 00 00 00 |0?......X.......|
000000e0 30 3f 00 00 04 00 00 00 00 00 00 00 00 00 00 00 |0?..............|
000000f0 00 04 00 80 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 5f 5f 73 74 75 62 73 00 00 00 00 00 00 00 00 00 |__stubs.........|
00000110 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000120 88 3f 00 00 01 00 00 00 06 00 00 00 00 00 00 00 |.?..............|
00000130 88 3f 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |.?..............|
00000140 08 04 00 80 00 00 00 00 06 00 00 00 00 00 00 00 |................|
[...]
```
objdump -D foo
[...]
100003f30: 55 pushq %rbp
100003f31: 48 89 e5 movq %rsp, %rbp
100003f34: 48 83 ec 10 subq $16, %rsp
100003f38: c7 45 fc 00 00 00 00 movl $0, -4(%rbp)
100003f3f: c7 45 f8 00 00 00 00 movl $0, -8(%rbp)
100003f46: c7 45 f4 00 00 00 00 movl $0, -12(%rbp)
100003f4d: 83 7d f4 64 cmpl $100, -12(%rbp)
100003f51: 0f 8d 17 00 00 00 jge 0x100003f6e <_main+0x3e>
100003f57: 8b 45 f8 movl -8(%rbp), %eax
100003f5a: 83 c0 0a addl $10, %eax
100003f5d: 89 45 f8 movl %eax, -8(%rbp)
100003f60: 8b 45 f4 movl -12(%rbp), %eax
100003f63: 83 c0 01 addl $1, %eax
100003f66: 89 45 f4 movl %eax, -12(%rbp)
100003f69: e9 df ff ff ff jmp 0x100003f4d <_main+0x1d>
[...]
addl
meand add
, jmp
means jump and so forth. This is not important for now, the point is that gcc
which is a popular C compiler, will take your code and make it into machine code.
Lets have another example:
FizzBuzz
```
include
int main() {
for (int i = 0; i < 100; i++) {
if (i % 15 == 0) {
printf("fizzbuzz\n");
} else if (i % 5 == 0) {
printf("buzz\n");
} else if (i % 3 == 0) {
printf("fizz\n");
} else {
printf("%d\n",i);
}
}
}
```
What is your name?
```
include
int main() {
char input[20] = {0};
while(1) {
printf("What is your name: ");
scanf("%s",input);
printf("\nHello %s\n",input);
}
}
```
You see how we say char input[20]
which means we habe 20 elements of type char
pointed by the input variable, it is literally just a pointer to some memory, and we can use input[1]
to go to the address input
plus 1 byte. Same with int x[10]
, if we do x[3], it will go to the address pointed by x
and add 3 * 4 to it.
We can make interesting bugs like that, because nobody will check if we go and read somewhere outside of the defined array:
```
include
int main() {
char input[20] = {0};
int b = 5;
while(1) {
printf("What is your name: ");
scanf("%s",input);
printf("\nHello %s\n",input);
for (int i = 0; i < 40; i++) {
printf(" %d -> %d -> %c\n", i, input[i],input[i]);
}
}
}
```
You will see some garbage from element 20 to 39, because it will actually go and read beyond the input bounderioes.
[DAY-137] For; File; If
Play with words.txt
Open the file and print all the lines:
f = open("words.txt")
for line in f:
print(line)
Remove the newline:
f = open("words.txt")
for line in f:
word = line.strip()
print(word)
Print only words with more than 10 characters:
f = open("words.txt")
for line in f:
word = line.strip()
if len(word) > 10:
print(word)
Print only words starting with 'ab':
f = open("words.txt")
for line in f:
word = line.strip()
if word[0] == 'a' and word[1] == 'b':
print(word)
Print words not containing a character
f = open("words.txt")
for line in f:
word = line.strip()
if 'e' not in word:
print(word)
Avoid words containing multiple characters
```
f = open("words.txt")
def avoid(word, characters):
for c in characters:
for w in word:
if w == c:
return False
return True
for line in f:
word = line.strip()
if avoid(word, ['a','b','c']):
print(word)
```
Another implementation using 'char' in 'string':
```
f = open("words.txt")
def avoid(word, characters):
for c in characters:
for c in word:
return False
return True
for line in f:
word = line.strip()
if avoid(word, ['a','b','c']):
print(word)
```
Spinning turtle
import turtle as t
size = 10
t.speed(10000)
while True:
t.right(150)
t.forward(size)
size += 1
```
import turtle as t
size = 10
t.speed(10000)
while True:
t.right(150)
t.forward(size)
if size % 2 == 0:
t.color('cyan')
else:
t.color('magenta')
size += 1
```
import turtle as t
size = 1
t.speed(100000)
t.bgcolor('black')
t.hideturtle()
i = 0
while True:
if i % 2 == 0:
t.color('cyan')
else:
t.color('magenta')
t.forward(i*3)
t.left(91)
i+=1
from turtle import *
begin_fill()
color('red')
pensize(3)
left(48)
forward(133)
circle(50,200)
right(140)
circle(50,200)
forward(133)
end_fill()
done()
```
from turtle import *
size = 1
speed(10000)
while True:
if size % 2 == 0:
color('blue')
else:
color('red')
circle(size, size * 5)
size += 1
```
[DAY-138] For; File; If
Take it easy.
Count how many lines have exactly 5 characters
fi = open('words.txt')
n = 0
for line in fi:
w = line.strip()
if len(w) == 5:
n += 1
print(n)
How many words have 7 and how many 5 characters?
fi = open('words.txt')
n = 0
x = 0
for line in fi:
w = line.strip()
if len(w) == 5:
n += 1
if len(w) == 7:
x += 1
print(n)
print(x)
[DAY-139] While; List; Counter
First touchtype for 20 minutes.
Then do some chill turtle shapes.
```
from turtle import *
speed(100000)
pencolor('cyan')
size = 66
while True:
forward(size)
left(size)
size += 1
```
```
from turtle import *
c = ['cyan','magenta']
dist = 20
hideturtle()
speed(11)
while True:
color(c[dist%2])
forward(dist)
left(90)
dist = dist-3
```
[DAY-140] While; Turtle; Strings
Read the strings chapter in the Thinking Python book.
Then do some chill turtle shapes.
```
import turtle
import random
turtles = []
for i in range(5):
a = turtle.Turtle()
a.speed(10000)
a.hideturtle()
turtles.append(a)
while True:
for x in turtles:
size = random.randint(10,300)
extent = random.randint(0, 360)
x.circle(size, extent=extent)
```
```
import turtle
import random
turtles = []
for i in range(5):
a = turtle.Turtle()
a.speed(10000)
a.hideturtle()
turtles.append(a)
while True:
for x in turtles:
size = random.randint(10,300)
for i in range(4):
x.forward(size)
x.right(90)
x.circle(size)
```
```
import turtle
import random
turtles = []
for i in range(5):
a = turtle.Turtle()
a.speed(10000)
a.hideturtle()
turtles.append(a)
while True:
for x in turtles:
size = random.randint(10,300)
for i in range(4):
x.forward(size)
x.right(90)
```
```
import turtle
import random
turtles = []
for i in range(5):
a = turtle.Turtle()
a.speed(10000)
a.hideturtle()
turtles.append(a)
while True:
for x in turtles:
size = random.randint(10,300)
x.circle(size)
```
[DAY-141] Wiki; API
Today we are going to make a small app that uses wikipedia. First install the wikipedia package:
pip3 install wikipedia
```
import wikipedia as wiki
while True:
what = input("search> ")
summary = wiki.summary(what)
print(summary)
print('*' * 40)
```
Will search wikipeadia the string you input, like this:
search> leonadro da vinci
Leonardo da Vinci (15 April 1452 – 2 May 1519) was an Italian polymath of...
[...]
search>
Lets do the same but with pygame:
```
import wikipedia as wiki
import pgzrun
HEIGHT = 800
WIDTH = 800
text = ''
info = ''
def on_key_down(key, mod, unicode):
global text, info
if key == keys.BACKSPACE:
if len(text) > 0:
text = text[:-1]
elif key == keys.RETURN:
info = wiki.summary(text)
text = ''
elif len(unicode) > 0 and ord(unicode) >= 32 and ord(unicode) <= 126:
text += unicode
def draw():
screen.clear()
screen.draw.text(info, (10,10), fontsize=18,fontname="437-win", width=WIDTH-20)
screen.draw.text(text, (WIDTH/2,HEIGHT - 40), color=(255,0,0), fontsize=30,fontname="437-win")
pgzrun.go()
```
What does this do actually? How does the wikipedia module work? First thing you want to check is the documentation page, https://pypi.org/project/wikipedia/ and then you can also check the source code: https://github.com/goldsmith/Wikipedia
Next you would like to think, how would this python module download the data from wikipedia.
What it actually does, is it opens a web page, just a page that is specifically made to be easier to be read with programs, try to open: https://en.wikipedia.org/w/api.php?action=query&prop=extracts&format=json&explaintext=&titles=Dog which will be the page for Dog
, you will see:
{"batchcomplete":"","query":{"pages":{"4269567":{"pageid":4269567,"ns":0,"title":"Dog","extract":"The dog or domestic dog
[...]
an end to the dinosaurs and the appearance of the first carnivoran...
[...]
Their personality traits include hypersocial behavior, boldnes
[...]
You can see the equivalent HTML page at https://en.wikipedia.org/wiki/Dog, The other page, which had structured data easier to read by python and any other programming language, is called API, Application Proggramming Interface. It just means that someone thought explicitly that their output will be read by programs and not people, and so they designed the interface that way. In the wikipedia example they return JSON.
JSON is data serialization format, its goal is to make it easy for programs to exchange data, for example I can have an array, or dictionary, and I want to make it easy for some other program to read it, so I use JSON to make it into text with special rules, and they can use their JSON decoder to make it into data.
```
import json
a = {"a":"b","c":3}
print(json.dumps([1,2,a]))
[1, 2, {"a": "b", "c": 3}]
d = json.loads('[1, 2, {"a": "b", "c": 3}]')
d
[1, 2, {'a': 'b', 'c': 3}]
```
You see how it looks similar to the wikipedia API output, we will go in depth in the JSON format some times later, the point now is to just recognize that there is a whole world of APIs that are gluing the programs on your computer, and even the internet together so they can communicate. JSON is one of the most common serialization protocol, but there are many many more.
[DAY-142] While
today is again, chill turtle art
ever growing circle
from turtle import *
speed(0)
size = 0
hideturtle()
while True:
size += 1
circle(size)
evergrowing circle and also go into negative radius
from turtle import *
speed(0)
size = 300
hideturtle()
while True:
size -= 1
circle(size)
stop when the bottom circle is the same as the top one
from turtle import *
speed(0)
size = 300
hideturtle()
while True:
size -= 1
circle(size)
if size < -300:
break
done()
make the circles more edgy
from turtle import *
import random
speed(0)
size = 300
hideturtle()
while True:
#size -= 1
circle(size, steps=random.randint(10,20))
if size < -300:
break
done()
[DAY-143] Strings
Print the characters of a string one by one:
a = 'hello'
for i in a:
print(i)
Print the characters and their index:
a = 'hello'
for i in range(0,len(a)):
print(i, a[i])
Reverse the characters:
a = 'hey'
rev = ''
for i in range(0,len(a)):
# i = 0
# a[2 - 0] -> a[2] -> y
# i = 1
# a[2 - 1] -> a[1] -> e
# i = 2
# a[2 - 2] -> a[0] -> h
print(i,a[len(a)-1-i])
rev +=a[len(a)-1-i]
print(rev)
Google 'how to reverse a string in python'
a = 'hello'
b = a[len(a)::-1]
print(b)
check out the stackoverflow explanation at https://stackoverflow.com/questions/509211
Answer by Greg Hewgill, https://stackoverflow.com/users/893/greg-hewgill
```
It's pretty simple really:
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
There is also the step value, which can be used with any of the above:
a[start:stop:step] # start through not past stop, by step
The key point to remember is that the :stop value represents the first value that
is not in the selected slice. So, the difference between stop and start is the
number of elements selected (if step is 1, the default).
The other feature is that start or stop may be a negative number, which means it
counts from the end of the array instead of the beginning. So:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
Similarly, step may be a negative number:
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Python is kind to the programmer if there are fewer items than you ask for. For example,
if you ask for a[:-2] and a only contains one element, you get an empty list instead of
an error. Sometimes you would prefer the error, so you have to be aware that this may happen.
Relation to slice() object
The slicing operator [] is actually being used in the above code with a slice() object
using the : notation (which is only valid within []), i.e.:
a[start:stop:step]
is equivalent to:
a[slice(start, stop, step)]
Slice objects also behave slightly differently depending on the number of arguments,
similarly to range(), i.e. both slice(stop) and slice(start, stop[, step]) are
supported. To skip specifying a given argument, one might use None, so that e.g.
a[start:] is equivalent to a[slice(start, None)] or a[::-1] is equivalent to
a[slice(None, None, -1)].
While the :-based notation is very helpful for simple slicing, the explicit use of
slice() objects simplifies the programmatic generation of slicing.
```
[DAY-144] Strings; Lists
Sum the ascii of the elements of a list.
```
a = ['h','e','l','l','o']
sum = 0
for i in a:
sum += ord(a)
print(sum)
```
Print its index, and the letter with the corresponding ascii
```
a = ['h','e','l','l','o']
sum = 0
for i in range(len(a)):
m = ord(a[i])
print('index: ', i, a[i], '=', m)
sum += m
print(sum)
```
Now do the same with a string
```
a = 'hello'
sum = 0
for i in range(len(a)):
m = ord(a[i])
print('index: ', i, a[i], '=', m)
sum += m
print(sum)
```
See how lists and strings both have len() and are indexable, meaning you can go to a specific index a[i] and do something.
You can mutate (change) the list, meaning you can change its content
a = ['h','e','l','o']
a[2] = 'b'
print(a)
But you can not change a string inplace:
a = 'hello'
a[2] = 'b'
print(a)
You will get TypeError: 'str' object does not support item assignment
. If you want to change a string, you have to make a new one and reasign the variable to point to the new string.
```
a = 'hello'
a = a[0:2] + 'b' + a[3:5]
```
See how we make completely new string, made up from the parts of the old string, and also the letter 'b' in the middle, and we make the variable a
point to the new string.
[DAY-145] While
More turtle
```
import turtle as t
import random
t.bgcolor('black')
t.pensize(6)
t.speed(0)
size = 20
colors =['cyan','royalblue','lawngreen','red','purple','white','yellow']
while True:
t.pencolor(random.choice(colors))
t.circle(size)
t.left(12)
size += 1
```
```
from turtle import *
size = 20
speed(0)
hideturtle()
while True:
size += 5
circle(size)
```
```
import turtle as t
size = 0
t.speed(0)
while True:
t.forward(size)
t.left(90)
size += 1
```
Lets talk again about Memory.
a = 'hello'
print(len(a))
a += 'b'
print(len(a))
print(a[2])
First lets imagine a simplified representation of the string 'hello' in memory.
Lets imagine the computer memory as a long line of numbered boxes, so we can go directly to specific box
[-------------------------------------------------------------------------]
0 1024
Each of the boxes can contain value between 0 and 255, so in order to store our string, we need at least 5 boxes, one for each letter, the memory does not understand such thing as character, only numnbers between 0 and 255, that is why we have the ASCII table, to have a standard how to represent characters as numbers in a common way. So we will store h
which is 104 and, e
which is 101, etc
Lets say that python finds out some free memory at address 555, and we just store 104,101,108,108,111, The problem with that is that we dont know when the string actually ends, so either we have to read to the first 0
, or we have to store the length of the string, and usually you store the length. So we will store the number 5, which we know is the length, and then the ASCII characters.
[--------------5 104 101 108 108 111----------------------------------------------]
0 ^ 1024
555
Now the variable a
just points to box 555, when we do len(a)
we can just read the number stored at this address, and when we do a[1]
we can read the value at address 555 + 1 + 1
which will give us (101)
What happens now when we do a += 'b'
, this is the same as a = a + 'b'
, which means ok, lets make a new string, with size 6
copy the original string there, and then add b
(which is 98 in ascii) to the end. So python will try to find a space in memory for at least 7 bytes (6 for the string, and one for the lenth), and do the copy.
[--------------5 104 101 108 108 111------6 104 101 108 108 111 98----------------]
0 ^ ^ 1024
555 763
Imagine the next free space in memory is on address 763, it will copy the data from address 556 to 560 to address 764 to 769, it will put 98
on address 770 and of course it will place the number 7
(the length of the new string), on address 763. And now we have a new string, it will just re-assign the variable a
to point to 763 instead of 555. Now the string on address 555 is not referenecd by any variable, and if it is not used by anything else (e.g. a list that also points to it), it can be garbage collected, and memory can be marked as free.
Lets talk about this code:
a = 'he'
b = 'lo'
c = 6
d = [a,b,c]
print(d[1])
One way python could represent a list is very similar to a string, you have length, and just addressess of the elements
[---3 555 763 847-----------2 104 101 ----------------2 108 111 ------6-----------]
0 ^ ^ ^ ^ 1024
125 555 763 847
The variable d will point to address 125
, from there you have first element on address 555, second on 763 and third on 847, to do print(d[1]
) means go to 125 + 1 + 1, and follow the pointer, so go to 555 ... and so on.
See there is a small problem because now python does not know if certain address contains a string, number or a list, so usually you need one more byte of information for the type of the object. Imagine 1 is for integer, 2 for string and 3 for list.
[---3 2 555 763 847-------2 2 104 101 --------------2 2 108 111 -----1 6----------]
0 ^ ^ ^ ^ 1024
125 555 763 847
ok now its eaier :) we know when we go to certain address of some data what to expect, so we know if we should print ascii or the number itself, or follow the reference to wherever it goes.
[DAY-146] While; Classes
Circles And Squares.
```
import turtle as t
a = t.Turtle()
a.speed(0)
a.pencolor('fuchsia')
b = t.Turtle()
b.speed(0)
b.pencolor('mediumspringgreen')
c = t.Turtle()
c.speed(0)
c.pencolor('deepskyblue')
size = 30
while True:
a.forward(size2)
a.left(90)
b.forward(size 3)
b.right(90)
c.forward(size*4)
c.right(90)
c.circle(size+1)
size += 2
```
```
import turtle as t
import random
a = t.Turtle()
a.speed(0)
b = t.Turtle()
b.speed(0)
b.hideturtle()
a.hideturtle()
b.pensize(5)
a.pensize(4)
b.pencolor('chocolate')
b.right(90)
b.forward(300)
size = 0
for i in range(70):
a.pencolor(random.choice(['red','orange','yellow','hotpink','magenta','deepskyblue','mediumspringgreen']))
b.right(180)
a.circle(size,extent=90)
a.forward(10)
a.right(5)
size += 1
t.done()
```
[DAY-147] While
Another flower
```
import turtle as t
a = t.Turtle()
a.speed(0)
a.right(90)
a.forward(300)
a.hideturtle()
b = t.Turtle()
b.speed(0)
b.hideturtle()
def square(charlie, size):
for i in range(4):
charlie.forward(size)
if i == 1:
charlie.write(str(size))
charlie.right(90)
size = 0
while True:
square(b,size)
b.right(9)
size += 1
if size > 125:
break
t.done()
```
[DAY-148] Money
Every time you use something, ask yourself how does the company that made it make money. How can it be so expensive or so cheap, or worse, how can it be free.
Most of the things you own and use are made by for-profit companies, for-profit means that the company tries to maximize its revenue and profit. This is in contrast with non-profit organizations, which does not try to make more money than it needs in order to function. For example Wikipedia is run by Wikimedia Foundation, which is a non profit organization.
Revenue means how much money comes in the company by selling its products, and profit means the revenue minus the expenses it has to produce the product. For example, if we have a company to make video games, and we pay ourselves 1000 euro in salary, and we sell each video game for 2 euro, then if we sell 600 video games, we will have 1200 euro in revenue, and 200 euro in profit: 1200 revenue - 1000 expense = 200 profit
.
The profit also taxed, so we have to pay some percent from the profit to the government, lets say its 10%, so from 200 euro profit, we will pay 20 euro to the government, it will use those money to pay its employees, and pay for health insurance, social insurance, build infrastructure, and maybe small percent of those will go to research and development projects, such as CERN (a huge 30 kilometer underground tunnel with magnets, that smashes protons together to see what happens when they collide with speeds closer to the speed of light) or the international space station.
After all that, we will be left with 180 euro profit. Almost every for-profit organization will try to maximize this number, for example one way we can increase this is if we try to reduce the expenses, imagine we pay less for the developers and we pay them 800 euro instead of 1000, then it seems we will get 400 euro in profit (or 360 after tax), but maybe those developers will make a worse game, so we wont eb able to sell 600 copies, and we sell 450, and then instead of getting 400 profit we get 900 revenue - 800 expense = 100 profit
, or 90 after tax.
Now think about what it means for something to be free, like Fortnite, or Roblox, or TikTok or Instagram, or when something is sold below its production cost, like the PlayStation 3.
Lets take the PlayStation as an example, they were selling the console for 600$, but it cost them 840$ to produce, why would they do that? First think how Sony makes money, each game you buy for 60$ Sony gets 30%, so 18$ goes to sony, when you buy 20 games through the year, which is what an average person spends on video games, they get 360$ profit, so in one year they will break even after 1 year, but people use the same video console for multiple years, so every consecutive year they get more and more profit.
So on the surface it might seem like Sony is making money on the console itself, but this is actually not true.
Lets go over Roblox, how do they make money? Every developer that makes a game there is taking a cut from all the robux spent by players, and Roblox is taking 75.5% of each transaction, so when you buy something for 10$ roblox gets 7.5$ and the developer gets 2.5$. Roblox is distributed through Apple's app store, how does Apple make money? they take 30% of all payments made oh the platform, so apple will take 30% as well, so the 10$ you pay, 3$ go to Apple, 5.3$ goes to Roblox and 1.7$ goes to the developers (the content creators of roblox).
Now there are other companies, such as Facebook, where they actually do not sell you anything, but they sell you to their customers. They are selling the fact that they can make you do something you did not intend to do, like buy a skateboard or buy karaoke machine, so they use that to sell it to for-profit corporations who make skateboards and karaoke machines.
In order for them to do that, they need to be very very precise with their predictions, what exactly they can make you do and when. That requires immense amount of data, so they have to track every possible thing. For example when you are walking, your phone has an accelerometer that can see how is the phone oriented in space so just by that they can see when you are walking to somebody, or when you are in the same mall with somebody, or are you in school? which people are in the same school because the basket you put your phones in is the same for all students in your class, etc. They must record every time you scroll a video, or you hesitate to scroll.
Facebook makes about 30 euros per month for each user they are selling.
Homework:
Why do you think whatsapp is free?
Why is primary education free?
Why is google translate free?
Why is google maps free?
Why is google search free?
Why is fortnite free?
Why is youtube free?
How is tocaboca making money?
How are the youtube content creators making money?
How does H&M make money?
How does the government make money?
A good thing to think about is also why are some things so expensive, how can we have smartphones for 50$ and for 2000$, what is the difference, Apple's hardware is surely expensive but is the difference between 32G phone ans 128G phone really that much? Why are the airpods 200$ when there are better headphones for 100$. Apple's physical product is not just the product you are buying, you are also buying the apple brand, which is valued very highly by the people. So even if somebody makes "better" product physically, it is not better overall, and many people still prefer Apple.
It is important to think about the product sa s combination of things, the physical/virtual product, the experience, the story, the brand, the scarcity, the timing.. everything is important.
Interestingly Apple first makes money by selling you the devices, and secondly they make money from each in-app purchase you do on those devices (e.g. robux or fortnite money). Apple made 33 billion dollars from the app store alone.
How much can a company optimize its profits? Some companies are abusing humans in the other end of the world so the product is cheaper and more competitive. The moment one company does that, all other companies have no option but to do the same thing so they are competitive. Imagine H&M or C&A, how come a jacket costs 20$? and it comes in all the way from China, it is made, loaded on a ship, sailed for 1 month and came to Rotterdam, where it was put on a truck and then an employee unloaded it and put it on display in the Mall, where they have to pay at least 20000$ per month rent. How much does the cotton cost? How much it costs to be picked from the plants, and then made into fabric, sewed and packed? How can the jacket be 20$?
This is called 'race to the bottom', when one company discovers a way to make their products cheaper, the other companies have to immidiately adapt otherwise they will lose their customers. Imagine tomorrow a new company comes and starts selling jackets for 15$, then H&M has to figure out how to make them for 15$ instead of 20$. Maybe H&M will make a contract with Apple and put 'APPLE IS THE BEST' on their jackets and then reduce the cost to 15$, or it will find a way to reduce the amount of cotton it uses, or will come up with more innovative technology to make the sewing cheaper, or it will hire cheaper labor. Sometimes they will say, oh lets sell online so we dont have to pay 20000$ per month for rent in the mall.
The 'race to the bottom' is very interesting, because it seems its making things cheaper and faster, but it is also decreasing the salaries as much as it possibly can, the salaries of the very same people who are also buying products. So they actually have less money to buy products, which makes it even more important to build cheaper products. But there are certain minimums, like raw resources needed, for example how much ground you have to grow cotton on is fixed.
Another thing that H&M can do, is simply talk with C&A and agree that they wont sell jackets below 20$, regardless how much it costs them to make, so if someone finds a way to make them for 15$ they will just make 5$ more profit, because the consumers can only chose between 20$ jackets. Or they can buy all other manufacturers of jackets and start selling jackets for 60$ instead of 20, purely because they can. The government has rules about how companies can merge together, and is trying to protect its citizens from situations like that, but it is very very difficult thing to regulate.
A lot of people in the world work as much as it is required so they do not get fired, and their employers pay them the minimum so they dont quit. The relationship between worker and employer is very complicated. You will see when you grow up, you will have jobs that you hate, and jobs that you love. Be especially carefull with the jobs that you love.
They say 'do what you love and never work a day in your life', but what they dont say, is that you are consuming that love, little by little, like an artist who is paid to draw something she thinks is ugly, she will need the money, and the real price the artist will pay is love. The love for your craft is not infinite. It is ok to hate your job, it is also ok to love your job.
You will study a lot of theories when you grow up, about how money flows, or how the free market works, or how the capitalist or socialist system is flawed, the most important thig to remember is to go back to first principles: how is something made, who makes it and who profits from it
, and profit does not have to be money, could be anything that people value such as: comfort, status, fame, pride, etc.
You see those forces, of the companies competing to get cheaper, sometimes they forget.. why do people use their product, even worse, sometimes they forget what their product really is. And then a new company comes, like a candle in a dark night, usually its only few people, maybe 2 or 3, working from their parent's garage, that can see what those companies can not see anymore. This is called disrupting the market. When new force appears, previously unknown, and people rejoice. The big corporations grinding their wheels create the right conditions, the right pressure, so a diamond is formed.
You can be that person, that disrupts. Every time you create something that people want, you disrupt it a bit, and sometimes your creation will resonate with the people's frequency, this is called product market fit.
[DAY-149] Creators, Consumers and Ideas
Every human in the world has brilliant ideas, multiple ideas per week. Most of the ideas are not good, but everyone has few great ideas per week. The problem is that nobody executes on those ideas, they just get forgotten and disappear. The execution of an idea is the real deal, the idea on its own is almost worthless. How many people do you think had the Fortnite idea before Epic games? Oh lets build Minecraft and Counter Strike together and booom Fortnite is born, I bet hundreds of developers thought about it, and many of them could've made it, but.. they didn't.
Today we will talk about why people do not make their ideas into being, and just forget them. There are usually many reasons, one of them is they think they cant make it, or they think its not good, or people wont like it. The problem is, it is extremely hard to evaluate an idea that is not obviously bad, withot putting a lot of effort and time into execution to actually see if it is worth it.
Lets just think outloud about some ideas:
Ninja Fortnite where you die if you are seen
Fifa Minecraft where you can build your field
Neighbourhood Nintendo Switch game exchange library
1 year photo collage with your friends, one photo per day from 5 people joined in a video
Dog meeting app, so you know when your dog's best friend is on a walk, so you can go together
Neighbourhood book exchange platform
make/write an augmented reality book
AR minecraft
AR lasertag
Those ideas came out just in few minutes. Now how would you decide which ones to buld? First, my advice is, build what you want to build right now . Just looking at this list, I could start working on AR minecraft right after I finish writing this sentence, just thinking about it it made me excited. However when you jump like that into execution of an idea, and you expect it to resonate with other people, you will be wrong most of the time, bencause your frequency is different than other people, so they might not like what you like.
If you want your product to be used by other people, you first have to carefully research if they would actually use and pay for what you are going to build. The process is as follows:
have an idea
build a super duper simple prototype that is totally broken, but good enough to illustrate the idea
use your prototype for some time
ask your friends to use your prototype
delete the prototype and start from scratch
build MVP - minimum viable product, which is a somewhat polished prototype that you can show to more people
ask for money as soon as possible, nothing says that people like your product like them paying money for it.
ask people if they like it, figure out what they do and dont like, and go back to change your MVP while you build on it
keep iterating on the MVP while you are building features on it, and at some point it will become product, instead of minimum viable product
even more simplified
step 1: build something [ with feedback ]
step 2: ask for feedback
step 3: ask for money if you can
step 4: goto step 1
In most cases (but not all), there is no better signal than people paying for your product. In some rare cases, you may be so ahead of the market, or have an insight which is invisible to others, that people don't even know they would pay for your product yet. The key question here is 'who do you ask', 'who are your users', 'how many are they in the world', 'how many you can reach with ads/marketing', 'how much are they willing to pay'. There is a lot of skill into figuring the answers to those questions.
If you want to make your idea not fail, you have to put in the effort, work with designers, and artists to help you build the MVP or the proof of concept. It is really hard to say if ideas fail because they are bad, or because the creators did not do a good job making it.
It is unprecedented, how few people are needed for an idea to come to life, sometimes only 1 person, a good developer, or designer is enough to completely make the MVP. A lot of that is because in the last 50 years we have dramatically improved the programming languages and tools. From assembler to python, from paint to photoshop, the productivity of a single person now is like an army of people in 1991.
A single person can change the world, most of the people however wont even try. 95% of the content in the internet is made by 5% of the people. 95% of the games in roblox is made by 5% of the players. The 5% is where all the fun is, I promise you, its like a rollercoaster.
[DAY-150] While; Classes
Circles And Squares.
```
from turtle import *
bgcolor('black')
a = Turtle()
a.speed(0)
a.hideturtle()
b = Turtle()
b.speed(0)
b.hideturtle()
colorA = textinput('pencolor a',"what is your name?:")
colorB = textinput('pencolor b',"what is your name?:")
size = 0
while True:
b.pencolor(colorB)
b.forward(size*3)
b.left(91)
a.pencolor(colorA)
a.forward(size*10)
a.circle(size, 360)
a.left(500)
size += 1
```
More circles
```
import turtle as t
t.bgcolor('black')
t.hideturtle()
size = -300
t.speed(0)
while True:
if size % 2 == 0:
t.pencolor('cyan')
else:
t.pencolor('magenta')
t.circle(size*3)
size += 1
```
[DAY-151] Classes; While
First make a painting program where you can chose colors and draw rectangles
```
import pgzrun
WIDTH = 800
HEIGHT = 800
elf = Actor('c1')
x = 0
y = 0
color = None
drop = []
size = 40
def update():
global color,size
if keyboard.W:
elf.y -= 5
if keyboard.S:
elf.y += 5
if keyboard.D:
elf.x += 5
if keyboard.A:
elf.x -= 5
if keyboard.C:
screen.clear()
if keyboard.SPACE and color != None:
drop.append([color, Rect(elf.x, elf.y, size, size)])
if keyboard.K_1:
color = (255,0,0)
if keyboard.K_2:
color = (25,41, 88)
if keyboard.K_8:
size += 1
if keyboard.K_9:
size -= 1
def draw():
screen.clear()
elf.draw()
for pixel in drop:
screen.draw.rect(pixel[1],pixel[0])
if color != None:
screen.draw.rect(Rect(elf.x,elf.y,size,size), color)
pgzrun.go()
```
Same program but making a Pixel class instead of a list with color and rect.
```
import pgzrun
WIDTH = 800
HEIGHT = 800
class Pixel:
def init (self, color, x, y, size):
self.color = color
self.rect = Rect(x,y,size,size)
def draw(self):
screen.draw.rect(self.rect, self.color)
elf = Actor('c1')
x = 0
y = 0
color = None
drop = []
size = 40
def update():
global color,size
if keyboard.W:
elf.y -= 5
if keyboard.S:
elf.y += 5
if keyboard.D:
elf.x += 5
if keyboard.A:
elf.x -= 5
if keyboard.C:
screen.clear()
if keyboard.SPACE and color != None:
pixel = Pixel(color, elf.x, elf.y, size)
drop.append(pixel)
if keyboard.K_1:
color = (255,0,0)
if keyboard.K_2:
color = (25, 41, 88)
if keyboard.K_8:
size += 1
if keyboard.K_9:
size -= 1
def draw():
screen.clear()
elf.draw()
for pixel in drop:
pixel.draw()
if color != None:
screen.draw.rect(Rect(elf.x,elf.y,size,size), color)
pgzrun.go()
```
Go back in the book and re-read the class chapter.
Try out some ideas with a class, just to understand better what self
is, for example play around with this Point class, try to add move_right
or move_up
methods.
```
class Point:
def init (self, x, y):
self.x = x
self.y = y
def move(self,x,y):
self.x = x
self.y = y
def move_left(self):
self.x -= 1
def show(self):
print(self.x, self.y)
def equal(self, other_point):
if self.x == other_point.x and self.y == other_point.y:
return True
return False
p1 = Point(10,20)
p2 = Point(30,40)
p3 = Point(10,20)
p3.move(50,60)
p1.show()
p2.show()
p3.move_left()
p3.show()
print(p3.equal(p1))
```
Completely unrelated and just for fun, make a triangle like pattern:
while True:
for i in range(0,10):
print(':3'* i)
for i in range(10,0,-1):
print(':D' * i)
Prints infinite sequence of smilies
```
:3
:3:3
:3:3:3
:3:3:3:3
:3:3:3:3:3
:3:3:3:3:3:3
:3:3:3:3:3:3:3
:3:3:3:3:3:3:3:3
:3:3:3:3:3:3:3:3:3
:D:D:D:D:D:D:D:D:D:D
:D:D:D:D:D:D:D:D:D
:D:D:D:D:D:D:D:D
:D:D:D:D:D:D:D
:D:D:D:D:D:D
:D:D:D:D:D
:D:D:D:D
:D:D:D
:D:D
:D
:3
:3:3
:3:3:3
:3:3:3:3
:3:3:3:3:3
:3:3:3:3:3:3
...
```
[DAY-152] Lists
Make 3 actors you can pick up and drop them wherever you hit SPACE.
```
import pgzrun
WIDTH = 500
HEIGHT = 500
king = Actor('c2')
elf = Actor('c1')
flower = Actor('flower')
rock = Actor('rock')
king.x = 480
king.y = 125
flower.y = 380
flower.x = 480
rock.x = 480
rock.y = 250
drop = []
speed = 5
def update():
global speed
if keyboard.W:
elf.y -= speed
if keyboard.S:
elf.y += speed
if keyboard.D:
elf.x += speed
if keyboard.A:
elf.x -= speed
if keyboard.C:
screen.clear()
if elf.colliderect(king):
elf.image=king.image
speed = 2
if elf.colliderect(rock):
elf.image=rock.image
speed = 1
if elf.colliderect(flower):
elf.image=flower.image
speed = 10
if keyboard.SPACE and elf.image != 'c1':
a = Actor(elf.image)
a.x = elf.x
a.y = elf.y
drop.append(a)
elf.image='c1'
speed = 5
def draw():
screen.clear()
elf.draw()
king.draw()
flower.draw()
rock.draw()
for d in drop:
d.draw()
pgzrun.go()
```
[DAY-153] Lists; Dictionaries
Find Waldo, here are two different implementations of the game, one uses dictionaries and one doesnt.
In this game, one of the actors has his back turned, and the purpose of the game is to find them.
We are using this example to practice lists, using for element in list
and for i in range(len(list))
, and overusing iterating over the list to find a matching element.
```
import pgzrun
import random
WIDTH = 800
HEIGHT = 800
elf = Actor('c1')
elf.x = 400
elf.y = 400
drop = []
def on_key_down(key):
if key == keys.SPACE:
found = False
for i in drop:
if i.image == 'c2-back':
found = True
if not found:
a = Actor('c2-back')
a.x = random.randint(0,1500)
a.y = random.randint(0,1500)
drop.append(a)
for i in range(100):
a = Actor('c2')
a.x = random.randint(0,2000)
a.y = random.randint(0,2000)
drop.append(a)
if key == keys.P:
for i in drop:
if i.image == 'c2-back':
i.x = random.randint(elf.x - 200,elf.x + 200)
i.y = random.randint(elf.y - 200,elf.y + 200)
waldo_found = False
def update():
global waldo_found
if keyboard.W:
for x in range(len(drop)):
i = drop[x]
i.y += 5
if keyboard.S:
for a in range(len(drop)):
drop[a].y -= 5
if keyboard.A:
for i in drop:
i.x += 5
if keyboard.D:
for i in drop:
i.x -= 5
for i in drop:
if i.image == 'c2-back' and elf.colliderect(i):
waldo_found = True
def draw():
screen.fill('black')
elf.draw()
for i in drop:
i.draw()
if waldo_found == True:
screen.draw.text(" YOU HAVE FOUND WALDO ", (10,10))
pgzrun.go()
```
A second implementation where we use a waldo
variable so we dont have to scan the list of actors so many times, and also we move the elf instead of moving all the actors. And we use a dictionary with positions to try to avoid adding an actor close to already existing one.
```
import pgzrun
import random
WIDTH = 800
HEIGHT = 800
elf = Actor('c1')
elf.x = 400
elf.y = 400
drop = []
waldo = Actor('c2-back')
seen = {}
def on_key_down(key):
if key == keys.SPACE:
waldo.x = random.randint(0,WIDTH)
waldo.y = random.randint(0,HEIGHT)
place = str(int(waldo.x/50)) + "" + str(int(waldo.y/100))
seen[place] = True
for i in range(100):
x = random.randint(0,WIDTH)
y = random.randint(0,HEIGHT)
place = str(int(x/50)) + " " + str(int(y/100))
if place not in seen:
a = Actor('c2')
a.x = x
a.y = y
drop.append(a)
seen[place] = True
waldo_found = False
def update():
global waldo_found
if keyboard.W:
elf.y -= 5
if keyboard.S:
elf.y += 5
if keyboard.A:
elf.x -= 5
if keyboard.D:
elf.x += 5
if waldo.colliderect(elf):
waldo_found = True
def draw():
screen.fill('black')
elf.draw()
for i in drop:
i.draw()
waldo.draw()
if waldo_found == True:
screen.draw.text(" YOU HAVE FOUND WALDO ", (10,10))
pgzrun.go()
```
[DAY-154] Classes
Pacman, make things move around, stop when they hit something
```
import random
import pgzrun
WIDTH = 600
HEIGHT = 600
game_over = False
lives = 3
obsticles = [
Rect(100,100,20,20),
Rect(200,200,100,200),
]
class Mover:
def init (self, image, x, y, direction):
self.actor = Actor(image)
self.direction = direction
self.actor.x = x
self.actor.y = y
self.counter = 0
def draw(self):
self.actor.draw()
def update(self):
orig_x = self.actor.x
orig_y = self.actor.y
self.counter += 1
if self.counter > 120 and self.actor.image == "c2":
self.direction = random.choice(['up','down','left','right'])
self.counter = 0
if self.direction == 'up':
self.actor.y -= 1
if self.direction == 'down':
self.actor.y += 1
if self.direction == 'left':
self.actor.x -= 1
if self.direction == 'right':
self.actor.x += 1
if self.actor.x > WIDTH:
self.actor.x = 0
if self.actor.x < 0:
self.actor.x = WIDTH
if self.actor.y > HEIGHT:
self.actor.y = 0
if self.actor.y < 0:
self.actor.y = HEIGHT
hit_wall = False
for o in obsticles:
if self.actor.colliderect(o):
self.actor.x = orig_x
self.actor.y = orig_y
hit_wall = True
break
if hit_wall and self.actor.image == "c2":
self.direction = random.choice(['up','down','left','right'])
pacman = Mover("c1", 10, 10, 'up')
movers = [pacman,
Mover("c2", 100, 40, 'up'),
Mover("c2", 100, 50, 'up'),
Mover("c2", 100, 60, 'up'),
Mover("c2", 100, 70, 'up')
]
def update():
global lives,game_over
if keyboard.W:
pacman.direction = 'up'
if keyboard.S:
pacman.direction = 'down'
if keyboard.A:
pacman.direction = 'left'
if keyboard.D:
pacman.direction = 'right'
for m in movers:
m.update()
for o in movers:
if pacman.actor.colliderect(o.actor) and o != pacman:
lives -= 1
pacman.actor.x = 0
pacman.actor.y = 0
if lives < 0:
game_over = True
def draw():
screen.fill('black')
for o in obsticles:
screen.draw.filled_rect(o,(255,0,0))
screen.draw.text('lives: ' + str(lives), (10,10))
if game_over == True:
screen.fill('royalblue')
screen.draw.text('GAME OVER YOU LOST',(10,10))
for m in movers:
m.draw()
pgzrun.go()
```
[DAY-155] c++
First lets discuss a bit about the difference between c++
and python
. For example, lets examine what happens with the following program:
while True:
print("hello world")
If you save it in the file hello.py
, and you have to start it with python hello.py
. Python is a program on its own, which will load the hello.py
file and execute it line by line. The python
program is called interpreter
because it interprets the code, kind of like when you read a program, trying to find out what it does, you interpret the code in your head and evaluate it.
c
and c++
on the other hand are compiled languages, you need a program gcc
for c and g++
for c++ to transform your source code to machine code, that your computer will directly run, instruction by instruction, gcc
and g++
are compilers.
Lets start where everything starts, print "Hello World". Save the following program in a file hello.cpp
(cpp for c plus plus).
```
include
using namespace std;
int main(void) {
cout << "Hello World " << endl;
}
```
Now lets compile it, g++ -o hello hello.cpp
will make a program hello
that you will be able to execute by running ./hello
you see it is very different, you run directly hello
which will make your computer execute its instructions one by one, which is very different than running python to load your hello.py
, in the python case your computer is running the python executable which loads your hello.py
and interprets it line by line.
int main()
declares the main
function, each c/c++ program must have a main() function, thats where your program starts, unlike python, where it starts from the top of the file. You can think of your processor jumping to the address of the main function in memory, as we spoke in the previous lessons, in the computer's memoruy code is data, and data is code.
cout
means character output
and <<
means pour into the cout
whatever follows, e.g. cout << 5
will just print 5, cout "hello"
will print hello, cout << 5 << "hello"
will print 5hello, and endl
inserts the newline character \n
.
using namespace std;
is similar to from turtle import *
, we will get into it later
And very importantly you c++
does not care about your spaces, the following program compiles just fine
```
include
using namespace std;int main(void) {cout << "Hello World " << endl;}
```
Each code block is surrounded by {}
and each statement ends with ;
and thats it
Try out the following programs, and just experiment with them using your python knowledge. (hint: int
means integer)
```
include
using namespace std;
int main(void) {
int i = 1000;
while(i) {
if (i < 500) {
cout << "HIII" << endl;
} else {
cout << "Hello World " << i << endl;
}
i--;
}
}
```
```
include
using namespace std;
int main(void) {
for (int i = 1000; i >= 0 ; i--) {
if (i < 500) {
cout << "HIII " << i << endl;
} else {
cout << "Hello World " << i << endl;
}
}
return 0;
}
```
[DAY-156] for; while
Write the same code with for and while loops.
```
include
using namespace std;
int main(void) {
int x = 3;
while(x < 3000000){
cout << x << endl;
x = x+3;
}
return 0;
}
```
```
include
using namespace std;
int main(void) {
for (int x = 0; x < 3000000; x = x + 3) {
cout << x << endl;
}
return 0;
}
```
```
include
using namespace std;
int main(void) {
for (int x = 10; x > 0; x = x - 1) {
cout << x << endl;
}
return 0;
}
```
```
include
using namespace std;
int main(void) {
int x = 10;
while(x > 0){
cout << x << endl;
x -= 1;
}
return 0;
}
```
```
include
using namespace std;
int main(void) {
int x = 0;
while (x < 10) {
cout << x << endl;
x+=1;
}
return 0;
}
```
```
include
using namespace std;
int main(void) {
for(int x = 0; x < 10; x += 1){
cout << x << endl;
}
return 0;
}
```
[DAY-157] strings; cin
Make love tester in python:
```
while True:
sum = 0
name1 = input('name 1: ')
name2 = input('name 2: ')
for i in range(len(name1)):
sum += ord(name1[i])
for i in range(len(name2)):
sum += ord(name2[i])
match = 1 + (sum % 100)
print("love test result:")
print(match)
```
Write the same program in c++:
```
include
using namespace std;
int main()
{
while(1) {
string name1;
string name2;
cout << "name1: ";
cin >> name1;
cout << "name2: ";
cin >> name2;
int sum = 0;
for (int i = 0; i < name1.size(); i++) {
sum += name1[i];
}
for (int i = 0; i < name2.size(); i++) {
sum += name2[i];
}
int match = 1 + (sum % 100);
cout << "love test result:" << endl;
cout << match << endl;
}
}
```
cin
is character input
, you can perform a read operation by geting data out of cin with >>
. Both cin
and cout
are streams. We will talk more about it later. For now just remember cin >> variable
will read from the input and put the value in variable
, and cout << variable
will print the value of the variable.
[DAY-158] if; while
rock paper scissors again
```
import random
options = ['rock','paper','scissors']
while True:
player = input(' '.join(options) + ': ')
if player not in options:
print("i dont know what to do with " + player)
continue
computer = random.choice(options)
print(computer)
if player == computer:
print("its a tie!")
if player == 'rock':
if computer == 'paper':
print('U lose the round')
elif computer == 'scissors':
print('U win this round')
if player == 'paper':
if computer == 'rock':
print('U win this round')
elif computer == 'scissors':
print('U lose the round')
if player == 'scissors':
if computer == 'rock':
print('U lose the round')
elif computer == 'paper':
print('U win this round')
```
sum things
```
data = ['hello','world','earth']
r = ''
for d in data:
r += d
print(r)
data = [1,2,3]
r = 0
for d in data:
r += d
print(r)
data = [[1,2],[3,4],[5,6]]
r = []
for d in data:
r += d
print(r)
```
The pattern, start with an empty result, iterate over the list and append append to the result is very very common. Examine the above code and notice how the part where it adds to the result is the same regardless if the list is list of strings, integers or list of lists
[DAY-159] strings; sizeof
Back to basics, how are strings layed out in memory, and how many bytes the primitive types occupy in memory:
```
include
using namespace std;
int main(void) {
char c = 'a';
int x = 'a';
bool b = true;
int sum = 0;
long l = 1;
short s = 1;
float f = 0.555;
double d = 0.4123123;
long double ld = 0.123123;
cout << "char" << sizeof(c) << endl;
cout << "bool" << sizeof(b) << endl;
cout << "int" << sizeof(sum) << endl;
cout << "short" << sizeof(s) << endl;
cout << "long" << sizeof(l) << endl;
cout << "float" << sizeof(f) << endl;
cout << "double" << sizeof(d) << endl;
cout << "long double" << sizeof(ld) << endl;
int ages[10]= {10,12,10,9,10,12,12,2,3,2};
cout << sizeof(ages) << endl;;
long double z[5] = {0,0,0,0,0};
cout << sizeof(z) << endl;;
char s1[10] = {'h','e','l','l','o','w','o','r','d','\0'};
char s2[] = "helloword";
cout << s1 << endl;
cout << s2 << endl;
}
```
argc and argv
```
include
using namespace std;
int main(int argc, char* argv[]) {
cout << "Have " << argc << " arguments:" << endl;
cout << "my name is: " << argv[0] << endl;
for (int i = 0; i < argc; ++i) {
cout << i << ": " << argv[i] << endl;
}
return 0;
}
``
Compile the the program above as
g++ -o xyz file.cpp, and run it with
./xyz hello world "aaa bbbb cccc" ddd. You see
g++has a
mainfunction as well, and it has
argcand
argv` as well.
Formatting example:
```
include
include
using namespace std;
int main(void) {
for (int fahr=0; fahr<=100; fahr+=10){
cout<< endl
<< setw(6)
<< setprecision(0)
<< fahr
<< setw(10)
<< setprecision(3)
<< 5.0/9.0 * (fahr-32.0);
}
cout << endl;
return(0);
}
```
[DAY-160] pointers
c/c++ pointes and arrays are sometimes confusing, we will come back to them multiple times, especially because strings are pointers to arrays of characters, it is important for the concept to "click". Do not worry if you dont get it at first (or at second, or at third) attempt.
There are two important operators '*' and '&', int *pa = &a
means we have a pointer (*
) to a variable of type int
equal to the address (&
) of variable a
. The value of pa
is just a number, it is literally the address of the memory where the value of a
will be.
The most important concept is that pa
is actually just a number, this is the actual value of pa
, and with *pa = 5
means, go to this place in memory and put 5 there, we can literally go anywhere in memory and put some value there.
Arrays are a continuous chunks of memory, char b[10]
means b
is a pointer to somewhere in memory where you hold 10
slots of type char
which is 10 bytes. so b
actually just holds the location of those 10 bytes. Thats right, b
is a pointer, we can do b[2] = 'a'
or *(b + 2) = 'a'
they are the same thing, as b[2]
means go to wherever b
points to, and add 2 slots of b
's type, same as *(b + 2)
.
Examine the following program:
```
include
using namespace std;
int main(int argc, char argv[]) {
int a = 7;
int pa = &a;
*pa = 8;
cout << a << endl;
int b[8] = {10,11,12,13,14,15,16,17};
cout << b << endl;
cout << (b + 3) << endl;
cout << *(b + 3) << endl;
cout << b[3] << endl;
return 0;
}
```
[DAY-161] if; while; functions
Tic tac toe with 9 variables, one for each position of the grid.
This is how the gameplay should look:
```
a b c
0 - - -
1 - - -
2 - - -
[x] enter position (row col): 0 a
a b c
0 x - -
1 - - -
2 - - -
[0] enter position (row col): 0 b
a b c
0 x 0 -
1 - - -
2 - - -
[x] enter position (row col): 1 a
a b c
0 x 0 -
1 x - -
2 - - -
[0] enter position (row col): 1 b
a b c
0 x 0 -
1 x 0 -
2 - - -
[x] enter position (row col): 2 a
a b c
0 x 0 -
1 x 0 -
2 x - -
x wins!
```
And this is the code:
```
include
using namespace std;
void render(char g0, char g1, char g2, char g3, char g4, char g5, char g6, char g7, char g8) {
cout << " a b c" << endl;
cout << "0 " << g0 << " " << g1 << " " << g2 << endl;
cout << "1 " << g3 << " " << g4 << " " << g5 << endl;
cout << "2 " << g6 << " " << g7 << " " << g8 << endl;
}
bool wins(char symbol, char g0, char g1, char g2, char g3, char g4, char g5, char g6, char g7, char g8) {
if (g0 == symbol && g1 == symbol && g2 == symbol) {
return true;
}
if (g0 == symbol && g3 == symbol && g6 == symbol) {
return true;
}
if (g0 == symbol && g4 == symbol && g8 == symbol) {
return true;
}
if (g1 == symbol && g4 == symbol && g7 == symbol) {
return true;
}
if (g2 == symbol && g5 == symbol && g8 == symbol) {
return true;
}
if (g3 == symbol && g4 == symbol && g5 == symbol) {
return true;
}
if (g6 == symbol && g7 == symbol && g8 == symbol) {
return true;
}
if (g6 == symbol && g4 == symbol && g2 == symbol) {
return true;
}
return false;
}
int main(void) {
char g0,g1,g2,g3,g4,g5,g6,g7,g8;
g0 = g1 = g2 = g3 = g4 = g5 = g6 = g7 = g8 = '-';
char symbol = 'x';
while(1) {
render(g0,g1,g2,g3,g4,g5,g6,g7,g8);
char row,col;
cout << "[" << symbol << "] enter position (row col): ";
cin >> row >> col;
cout << endl;
if (row == '0') {
if (col == 'a') {
g0 = symbol;
}
if (col == 'b') {
g1 = symbol;
}
if (col == 'c') {
g2 = symbol;
}
}
if (row == '1') {
if (col == 'a') {
g3 = symbol;
}
if (col == 'b') {
g4 = symbol;
}
if (col == 'c') {
g5 = symbol;
}
}
if (row == '2') {
if (col == 'a') {
g6 = symbol;
}
if (col == 'b') {
g7 = symbol;
}
if (col == 'c') {
g8 = symbol;
}
}
if (wins(symbol,g0,g1,g2,g3,g4,g5,g6,g7,g8)) {
render(g0,g1,g2,g3,g4,g5,g6,g7,g8);
cout << symbol << " wins!" << endl;
break;
}
if (symbol == 'x') {
symbol = '0';
} else {
symbol = 'x';
}
}
return 0;
}
```
[DAY-162] if; while; variables
Make Tic Tac Toe in python using 9 variables; Completely on your own.
(this is the code that she wrote)
```
def board(a1,a2,a3,b1,b2,b3,c1,c2,c3):
print(' ',1,2,3)
print('a ',a1,a2,a3)
print('b ',b1,b2,b3)
print('c ',c1,c2,c3)
def game():
a1 = '-'
a2 = '-'
a3 = '-'
b1 = '-'
b2 = '-'
b3 = '-'
c1 = '-'
c2 = '-'
c3 = '-'
xz = 'x'
while True:
board(a1,a2,a3,b1,b2,b3,c1,c2,c3)
ask = input(xz + ' choose a number from 1,2,3 and a letter from a,b,c: ')
if ask == 'a1':
a1 = xz
if ask == 'a2':
a2 = xz
if ask == 'a3':
a3 = xz
if ask == 'b1':
b1 = xz
if ask == 'b2':
b2 = xz
if ask == 'b3':
b3 = xz
if ask == 'c1':
c1 = xz
if ask == 'c2':
c2 = xz
if ask == 'c3':
c3 = xz
if a1 == xz and a2 == xz and a3 == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if a3 == xz and b3 == xz and c3 == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if a2 == xz and b2 == xz and c2 == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if a1 == xz and b1 == xz and c1 == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if c1 == xz and c2 == xz and c3 == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if b1 == xz and b2 == xz and b3 == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if c1 == xz and b2 == xz and a3 == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if a1 == xz and b2 == xz and c3 == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if xz == 'x':
xz = '0'
else:
xz = 'x'
game()
```
Another way to write the same program, using few function.
```
def print_board(a1,a2,a3,b1,b2,b3,c1,c2,c3):
print(' ',1,2,3)
print('a ',a1,a2,a3)
print('b ',b1,b2,b3)
print('c ',c1,c2,c3)
def win(xz, a1,a2,a3,b1,b2,b3,c1,c2,c3):
if a1 == xz and a2 == xz and a3 == xz:
return True
if a3 == xz and b3 == xz and c3 == xz:
return True
if a2 == xz and b2 == xz and c2 == xz:
return True
if a1 == xz and b1 == xz and c1 == xz:
return True
if c1 == xz and c2 == xz and c3 == xz:
return True
if b1 == xz and b2 == xz and b3 == xz:
return True
if c1 == xz and b2 == xz and a3 == xz:
return True
if a1 == xz and b2 == xz and c3 == xz:
return True
return False
def get_input(xz, a1,a2,a3,b1,b2,b3,c1,c2,c3):
ask = input(xz + ' choose a number from 1,2,3 and a letter from a,b,c: ')
if ask == 'a1':
a1 = xz
if ask == 'a2':
a2 = xz
if ask == 'a3':
a3 = xz
if ask == 'b1':
b1 = xz
if ask == 'b2':
b2 = xz
if ask == 'b3':
b3 = xz
if ask == 'c1':
c1 = xz
if ask == 'c2':
c2 = xz
if ask == 'c3':
c3 = xz
return a1,a2,a3,b1,b2,b3,c1,c2,c3
def game():
a1 = a2 = a3 = b1 = b2 = b3 = c1 = c2 = c3 = '-'
xz = 'x'
while True:
print_board(a1,a2,a3,b1,b2,b3,c1,c2,c3)
a1,a2,a3,b1,b2,b3,c1,c2,c3 = get_input(xz, a1,a2,a3,b1,b2,b3,c1,c2,c3)
if win(xz, a1,a2,a3,b1,b2,b3,c1,c2,c3):
print(xz + " WINS 🥳🥳🥳!!!")
break
if xz == 'x':
xz = '0'
else:
xz = 'x'
game()
```
Now the game loop is very obvious:
print the board
get the input and modify the variables
check if there is a winnner
swap the symbol (from x to 0 and from 0 to x)
But in the same time, when you read the functions it is a bit confusing what is a1 a2 a3.. etc. This is ok for such a small program, either way works fine, but when programs grow you have to think about 'wait if someone is reading this function, will it make sense', 'will my variable names make sense to someone else'.
[DAY-163] if; while; lists
Do the same tic tac toe but with a list instead of 9 variables
(this is the code that she wrote)
```
def board(g):
print(' ',1,2,3)
print('a ',g[0],g[1],g[2])
print('b ',g[3],g[4],g[5])
print('c ',g[6],g[7],g[8])
def game():
g = ['-','-','-','-','-','-','-','-','-']
xz = 'x'
while True:
board(g)
ask = input(xz + ' choose a number from 1,2,3 and a letter from a,b,c: ')
if ask == 'a1':
g[0] = xz
if ask == 'a2':
g[1] = xz
if ask == 'a3':
g[2] = xz
if ask == 'b1':
g[3] = xz
if ask == 'b2':
g[4] = xz
if ask == 'b3':
g[5] = xz
if ask == 'c1':
g[6] = xz
if ask == 'c2':
g[7] = xz
if ask == 'c3':
g[8] = xz
if g[0] == xz and g[1] == xz and g[2] == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if g[3] == xz and g[4] == xz and g[5] == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if g[6] == xz and g[7] == xz and g[8] == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if g[1] == xz and g[4] == xz and g[7] == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if g[0] == xz and g[3] == xz and g[6] == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if g[2] == xz and g[5] == xz and g[8] == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if g[0] == xz and g[4] == xz and g[8] == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if g[2] == xz and g[4] == xz and g[6] == xz:
print(xz+ ' Wins 🥳🥳🥳')
break
if xz == 'x':
xz = '0'
else:
xz = 'x'
game()
```
alternative way of writing this:
```
def board(g):
print(' ',1,2,3)
print('a ',g[0],g[1],g[2])
print('b ',g[3],g[4],g[5])
print('c ',g[6],g[7],g[8])
def check(g, xz, i1,i2,i3):
if g[i1] == xz and g[i2] == xz and g[i3] == xz:
return True
return False
def game():
g = ['-','-','-','-','-','-','-','-','-']
xz = 'x'
while True:
# print the board
board(g)
# get the input and update the game board
ask = input(xz + ' choose a number from 1,2,3 and a letter from a,b,c: ')
index = 0
if ask[0] == 'a':
index = 0 + int(ask[1]) - 1 # convert a1 to index 0, a3 to index 3
if ask[0] == 'b':
index = 3 + int(ask[1]) - 1 # convert b1 to index 3 and b3 to index 5
if ask[0] == 'c':
index = 6 + int(ask[1]) - 1 # convert c1 to index 6 and c3 to index 8
g[index] = xz
# check if we have a winner
# horizontal
if check(g,xz,0,1,2) or check(g,xz,3,4,5) or check(g,xz,6,7,8):
print(xz+ ' Wins 🥳🥳🥳')
break
# vertical
if check(g,xz,1,4,7) or check(g,xz,0,3,6) or check(g,xz,2,5,8):
print(xz+ ' Wins 🥳🥳🥳')
break
# diagonal
if check(g,xz,0,4,8) or check(g,xz,2,4,6):
print(xz+ ' Wins 🥳🥳🥳')
break
# swap the synmbol for the next turn
if xz == 'x':
xz = '0'
else:
xz = 'x'
game()
```
[DAY-164] pointers
Write a program to prepare for the test tomorrow. Its a test of abbreviations, from abbreviation to meaning. Make a program to help you study, it should ask you for a abbreviation and then you should write its meaning.
t.z.t -> ten zijner tijd
v.l.n.r -> van links naar rechts
e.d -> en dergelijk
nr. -> nummer
zg. -> zogenaamd
Gebr. -> gebroeders
dr. -> doctor
s.v.p -> s'il vous plait
t.o.v -> ten opzichte van
nl. -> namelijk
N.B. -> Nota Bene
sr. -> senior
jr. -> junior
C -> Celsius
etc -> etcetra
t.a.v -> ter attentie van
P.S. -> postscriptum
B. en W. -> Burgemeesteren Wethouders
NL -> Nederland
v.a -> vanaf
drs -> doctorandes
The program will have 2 lists with the same amount of elements, you should pick a random index, ask the user to type the meaning for abbreviations[i]
and compare it with meaning[i]
```
import random
def test(taal,toets):
i = random.randint(0,len(taal)-1)
f = input(taal[i]+ ': ')
if f == toets[i]:
print('corect')
else:
print("WRONG, one more try!")
f = input(taal[i]+ ': ')
if f == toets[i]:
print('corect')
else:
print('better luck next time the correct answer was: '+toets[i])
short = ['t.z.t','v.l.n.r','e.d','nr.','zg.','Gebr.','dr.',
's.v.p','t.o.v','nl.','N.B.','sr.','jr.','C',
'etc','t.a.v','P.S.','B. en W.','NL','v.a','drs']
long = ['ten zijner tijd','van links naar rechts','en dergelijk',
'nummer','zogenaamd','gebroeders','doctor',
"s'il vous plait",'ten opzichte van','namelijk',
'Nota Bene','senior','junior','Celsius',
'etcetra','ter attentie van','postscriptum',
'Burgemeesteren Wethouders','Nederland','vanaf','doctorandes']
for i in range(len(short)):
print(short[i] + ' -> ' + long[i])
while True:
test(short,long)
test(long, short)
```
[DAY-165] if; while
Another tic tac toe on your own
(this is the code she wrote)
```
def board(g):
print(' ',1,2,3)
print('a',g[0],g[1],g[2])
print('b',g[3],g[4],g[5])
print('c',g[6],g[7],g[8])
g = ['-']*9
idk = 'x'
while True:
board(g)
l = input(idk + 'choose a number 1,2,3 and a letter a,b,c: ')
if l == 'a1':
g[0] = idk
if l == 'a2':
g[1] = idk
if l == 'a3':
g[2] = idk
if l == 'b1':
g[3] = idk
if l == 'b2':
g[4] = idk
if l == 'b3':
g[5] = idk
if l == 'c1':
g[6] = idk
if l == 'c2':
g[7] = idk
if l == 'c3':
g[8] = idk
if g[0] == idk and g[1] == idk and g[2] == idk:
print(idk+' Won congratulations 🥳🥳🥳')
break
if g[3] == idk and g[4] == idk and g[5] == idk:
print(idk+' Won congratulations 🥳🥳🥳')
break
if g[6] == idk and g[7] == idk and g[8] == idk:
print(idk+' Won congratulations 🥳🥳🥳')
break
if g[0] == idk and g[3] == idk and g[6] == idk:
print(idk+' Won congratulations 🥳🥳🥳')
break
if g[1] == idk and g[4] == idk and g[7] == idk:
print(idk+' Won congratulations 🥳🥳🥳')
break
if g[2] == idk and g[5] == idk and g[8] == idk:
print(idk+ ' Won congratulations 🥳🥳🥳')
break
if g[2] == idk and g[4] == idk and g[6] == idk:
print(idk+ 'Won congratulations 🥳🥳🥳')
break
if g[0] == idk and g[4] == idk and g[8] == idk:
print(idk+' Won congratulations 🥳🥳🥳')
break
done = True
for e in g:
if e == '-':
done = False
if done:
print('Its a tie')
break
if idk == 'x':
idk = '0'
else:
idk = 'x'
board(g)
```
[DAY-166] if; while
Write tic tac toe on your own but 4x4 instead of 3x3.
(this is the code she wrote)
```
def board(g):
print(' ',1,2,3,4)
print('a',g[0],g[1],g[2],g[3])
print('b',g[4],g[5],g[6],g[7])
print('c',g[8],g[9],g[10],g[11])
print('d',g[12],g[13],g[14],g[15])
g = ['-']*16
idk = 'x'
while True:
board(g)
l = input(idk + 'choose a number 1,2,3 and a letter a,b,c: ')
if l == 'a1':
g[0] = idk
if l == 'a2':
g[1] = idk
if l == 'a3':
g[2] = idk
if l == 'a4':
g[3] = idk
if g[0] == idk and g[1] == idk and g[2] == idk and g[3] == idk:
print(idk+' Won congratulations 🥳🥳🥳')
break
# ...
if idk == 'x':
idk = '0'
else:
idk = 'x'
board(g)
```
[DAY-167] C; printf; scanf
We will use printf
to display text and scanf
to read text input from the user. First compile the following program, save it to a file hello.c
and run gcc -o hello hello.c
the C compiler we will use is called gcc
, just as the C++ compiler we used was called g++
, and the options are again -o
for 'output file name' and then the source code file hello.c
.
```
include
int main(void) {
int age = 0;
printf("How old are you: ");
scanf("%d",&age);
if (age > 10) {
printf("you are a grownup\n");
} else {
printf("are you a little kid, %d %d %c\n", age, 102, 103);
}
return 0;
}
```
Now lets read it line by line, first we make a variable age
of type integer
with initial value of 0
, then we print "How old are you" using printf
, and immidiately after tat we do scanf("%d",&age)
, first we say to scanf that we are looking for a integer %d
and then once it reads an integer to put it on memory where the variable age
is located at. With the &
symbol we take the memory address of the variable.
Then we compare if the age that the user entered is > 10, we print one thing, and if not we print printf("are you a little kid, %d %d %c\n", age, 102, 103);
this will print the age itself (the first %d) will use the second parameter which is age
, then the second %d will print 102, and then %c will print the ascii value of 103 (g).
Both printf and scanf's first argument is the formatting string, while it is printing or scanning the input, whenever it sees %d %c %f (digit, character, floating point number), it will read from the arguments you passed to it and do what you want, read or write depending if printf or scanf.
This is just the first steps towards C, dont worry if you dont get the &
thing and the memory address, with some practice things will click and it will all make sense.
Lets say your coputer has only 30 bytes of memory:
00-09|..........|
10-19|0000......| int age at memory address 10, occupying 4 bytes
20-29|..........|
30-39|PPPPPPPPPP| the program itself
&age
is the address of age, which is 10, its as simple as that, scanf
gets the value 10 as the location in memory in which it should write down the number that it processed from the user input.
[DAY-168] c; while; if
Rock paper scissors in C.
```
include
include
define ROCK 0
define PAPER 1
define SCISSORS 2
int main(void) {
while (1) {
int player;
printf("rock(0) paper(1) scissors(2): ");
scanf("%d", &player);
int computer = rand() % 3;
printf("player: %d, computer: %d\n", player, computer);
if (computer == player) {
printf("its a tie\n");
} else {
if (computer == ROCK && player == PAPER) {
printf("player wins\n");
}
if (computer == ROCK && player == SCISSORS) {
printf("computer wins\n");
}
if (computer == PAPER && player == ROCK) {
printf("computer wins\n");
}
if (computer == PAPER && player == SCISSORS) {
printf("player wins\n");
}
if (computer == SCISSORS && player == ROCK) {
printf("player wins\n");
}
if (computer == SCISSORS && player == PAPER) {
printf("computer wins\n");
}
}
}
return 0;
}
```
#define ROCK 0
just makes the c compiler to replace ROCK with 0 wherever it sees it in the source code.
#include <stdlib.h>
is needed for the rand
function, it returns an integer, but since we need a number from 0, 1, 2 we just do rand() % 3
, which will take the reminder from the random number and 3.
Try this in python:
for i in range(100000):
print(i, i % 3)
You will see:
0 0
1 1
2 2
3 0
4 1
5 2
6 0
7 1
8 2
9 0
10 1
11 2
12 0
13 1
14 2
15 0
16 1
17 2
18 0
19 1
20 2
21 0
22 1
23 2
24 0
25 1
26 2
27 0
28 1
29 2
30 0
31 1
32 2
33 0
34 1
35 2
36 0
37 1
38 2
39 0
40 1
41 2
42 0
43 1
44 2
45 0
46 1
47 2
48 0
49 1
50 2
51 0
52 1
53 2
54 0
...
[DAY-169] c; while; if
Battle ship in C.
Arrays are continous block of memory, for example int x[10]
creates 10 integers (4 bytes each, so 40 bytes block), you can access each element by its index from x[0]
to x[9]
, e.g. x[2] = 5
will set the 3rd element to be equal to 5.
In C it is very easy to have multi dimensional arrays, simply say int x[10][10]
and that creates 10x10 integers you can access by their row and column, we will use two dimensional array to store our boards for the battleship game. As usual, we use one hidden board with the ships and one display board with the guesses.
```
include
include
define SIZE 10
int main(void) {
int hidden[SIZE][SIZE];
int display[SIZE][SIZE];
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
hidden[i][j] = 0;
display[i][j] = 0;
}
}
// make 20 random ships
for (int i = 0; i < 20; i++) {
hidden[rand() % SIZE][rand() % SIZE] = 1;
}
while (1) {
// print the display board
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
printf("%d ", display[i][j]);
}
printf("\n");
}
// get the row and column from the user
int row, column;
printf("row column> ");
scanf("%d %d", &row, &column);
// modify the display board depending if ship is
// found in the hidden board or not.
if (hidden[row][column] == 1) {
display[row][column] = 1;
} else {
display[row][column] = 2;
}
}
return 0;
}
```
[DAY-170] pointers
Watch "What Are Pointers? (C++)", by javidx9 on youtube. https://www.youtube.com/watch?v=iChalAKXffs
[DAY-171] while; for; if; list
Build a chess game in 3 days.
day 1, build the board, black and white squares, think carefully about the algorithm how to alternate between the colors
day 2, build the basic movement, how to pick and drop a piece (use the pieces from https://joszs.itch.io/, they are licensed as CC 4.0 and are very very beautiful)
day 3, polish the pieces, make it possible to take a piece
todo: add queening the pawn code later
todo: add restrictions to illegal moves
This is the code that we wrote together, it actually took 3 days, 30 minutes per day, with a some help from the parent, but in the end its a (almost) working chess game.
```
import pgzrun
HEIGHT = 800
WIDTH = 800
board = []
black = [
Actor('chess/rook-black',anchor=(0,0), pos=(0,0)),
Actor('chess/knight-black',anchor=(0,0), pos=(100,0)),
Actor('chess/bishop-black',anchor=(0,0), pos=(200,0)),
Actor('chess/queen-black',anchor=(0,0), pos=(300,0)),
Actor('chess/king-black',anchor=(0,0), pos=(400,0)),
Actor('chess/bishop-black',anchor=(0,0), pos=(500,0)),
Actor('chess/knight-black',anchor=(0,0), pos=(600,0)),
Actor('chess/rook-black',anchor=(0,0), pos=(700,0)),
Actor('chess/pawn-black',anchor=(0,0), pos=(0,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(100,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(200,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(300,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(400,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(500,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(600,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(700,100)),
]
white = [
Actor('chess/pawn-white',anchor=(0,0), pos=(0,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(100,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(200,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(300,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(400,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(500,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(600,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(700,600)),
Actor('chess/rook-white',anchor=(0,0), pos=(0,700)),
Actor('chess/knight-white',anchor=(0,0), pos=(100,700)),
Actor('chess/bishop-white',anchor=(0,0), pos=(200,700)),
Actor('chess/queen-white',anchor=(0,0), pos=(300,700)),
Actor('chess/king-white',anchor=(0,0), pos=(400,700)),
Actor('chess/bishop-white',anchor=(0,0), pos=(500,700)),
Actor('chess/knight-white',anchor=(0,0), pos=(600,700)),
Actor('chess/rook-white',anchor=(0,0), pos=(700,700)),
]
x = 0
y = 0
block = 0
for i in range(1,65):
if block % 2 == 0:
board.append(Actor('chess/white',anchor=(0,0), pos=(x,y)))
else:
board.append(Actor('chess/black',anchor=(0,0), pos=(x,y)))
block += 1
x += 100
if i != 0 and i%8 == 0:
y += 100
x = 0
block+=3
pick_white = None
pick_black = None
elf = Actor("c1",ancor=(0,0))
king = Actor("c2")
def on_key_down(key):
global pick_white,pick_black
if key == keys.R and pick_white == None:
# pick up the piece below
for w in white:
if elf.colliderect(w):
pick_white = w
elif key == keys.R and pick_white != None:
for b in board:
# shouldnt be able to drop if there is already white piece there
if elf.colliderect(b):
for w in white:
if w != pick_white and b.colliderect(w):
return
# snap the white piece to the board
pick_white.x = b.x
pick_white.y = b.y
# take the black piece if there
for bl in list(black):
if bl.colliderect(pick_white):
black.remove(bl)
# drop it
pick_white = None
break
if key == keys.P and pick_black == None:
# pick up the piece below
for b in black:
if king.colliderect(b):
pick_black = b
elif key == keys.P and pick_black != None:
for b in board:
if king.colliderect(b):
# dont allow a drop if there is already a black piece there
for l in black:
if l != pick_black and b.colliderect(l):
return
# snap the black piece to the board
pick_black.x = b.x
pick_black.y = b.y
# take the white piece if there
for w in list(white):
if w.colliderect(pick_black):
white.remove(w)
# drop it
pick_black = None
break
def update():
global pick_white,pick_black
speed = 2
if keyboard.W:
elf.y -= 5
if keyboard.S:
elf.y += 5
if keyboard.A:
elf.x -= 5
if keyboard.D:
elf.x += 5
if keyboard.UP:
king.y -= 5
if keyboard.DOWN:
king.y += 5
if keyboard.LEFT:
king.x -= 5
if keyboard.RIGHT:
king.x += 5
# move the white piece with the elf
if pick_white != None:
pick_white.x = elf.x - 30
pick_white.y = elf.y - 30
# move the black piece with the king
if pick_black != None:
pick_black.x = king.x - 30
pick_black.y = king.y - 30
def draw():
screen.fill('deepskyblue')
for b in board:
b.draw()
for b in black:
b.draw()
for w in white:
w.draw()
elf.draw()
king.draw()
pgzrun.go()
```
[DAY-172] if
Add Queening the Pawn functionality, which means when a white/black pawn reaches the of the board it turns into a queen. Think a bit what that means, for a white pawn it reaches the end of the board when its .y property is 0, and for a black pawn when its 700. The only thing left to do is to actually check if we are holding a pawn.
```
...
shouldnt be able to drop if there is already white piece there
if elf.colliderect(b):
for w in white:
if w != pick_white and b.colliderect(w):
return
# snap the white piece to the board
pick_white.x = b.x
pick_white.y = b.y
# take the black piece if there
for bl in list(black):
if bl.colliderect(pick_white):
black.remove(bl)
# Queening the Pawn:
# pick_white.image is chess/pawn-white for the white pawn
# set the pick_white.image to chess/queen-white if it reaches the black end of the board
if pick_white.image == 'chess/pawn-white' and pick_white.y == 0:
pick_white.image = 'chess/queen-white'
# drop it
pick_white = None
break
...
```
and respective for the black pawn:
```
...
if pick_black.image == 'chess/pawn-black' and pick_black.y == 700:
pick_black.image = 'chess/queen-black'
# drop it
pick_black = None
...
```
[DAY-173] if; variables
Today we will make another rule, the pawns can not go backwards. Also we will cleanup the code a bit, and rename few variable so it is more readable, previously we had for b in board
and then we were using b.x
and etc, which was kind of confusing. We will rename it for for square in board
and you will see how much more readable the code is.
First if we want to check if something is going backwards we have to compare its current position with the previous position. In our case this is quite simple, we will make two variables x
and y
and once we select which piece we will be moving we will store the piece's .x and .y properties into our x
and y
variables.
After we have the original position it is just a matter of checking at the time of placing the piece if it is a pawn and if the original y position is bigger or smaller than the new position, depending which way is forward, for the black pawns up is downwards (y is growing), for white its upwards (y is decreasing).
This is the whole program again, because of the rename of some variables, it is easier to re-read it.
```
import pgzrun
HEIGHT = 800
WIDTH = 800
board = []
black = [
Actor('chess/rook-black',anchor=(0,0), pos=(0,0)),
Actor('chess/knight-black',anchor=(0,0), pos=(100,0)),
Actor('chess/bishop-black',anchor=(0,0), pos=(200,0)),
Actor('chess/queen-black',anchor=(0,0), pos=(300,0)),
Actor('chess/king-black',anchor=(0,0), pos=(400,0)),
Actor('chess/bishop-black',anchor=(0,0), pos=(500,0)),
Actor('chess/knight-black',anchor=(0,0), pos=(600,0)),
Actor('chess/rook-black',anchor=(0,0), pos=(700,0)),
Actor('chess/pawn-black',anchor=(0,0), pos=(0,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(100,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(200,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(300,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(400,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(500,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(600,100)),
Actor('chess/pawn-black',anchor=(0,0), pos=(700,100)),
]
white = [
Actor('chess/pawn-white',anchor=(0,0), pos=(0,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(100,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(200,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(300,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(400,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(500,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(600,600)),
Actor('chess/pawn-white',anchor=(0,0), pos=(700,600)),
Actor('chess/rook-white',anchor=(0,0), pos=(0,700)),
Actor('chess/knight-white',anchor=(0,0), pos=(100,700)),
Actor('chess/bishop-white',anchor=(0,0), pos=(200,700)),
Actor('chess/queen-white',anchor=(0,0), pos=(300,700)),
Actor('chess/king-white',anchor=(0,0), pos=(400,700)),
Actor('chess/bishop-white',anchor=(0,0), pos=(500,700)),
Actor('chess/knight-white',anchor=(0,0), pos=(600,700)),
Actor('chess/rook-white',anchor=(0,0), pos=(700,700)),
]
x = 0
y = 0
block = 0
for i in range(1,65):
if block % 2 == 0:
board.append(Actor('chess/white',anchor=(0,0), pos=(x,y)))
else:
board.append(Actor('chess/black',anchor=(0,0), pos=(x,y)))
block += 1
x += 100
if i != 0 and i%8 == 0:
y += 100
x = 0
block+=3
pick_white = None
pick_black = None
elf = Actor("c1",ancor=(0,0))
king = Actor("c2")
x = 0
y = 0
def on_key_down(key):
global pick_white,pick_black,x,y
if key == keys.SPACE and pick_white == None:
# pick up the piece below
for w in white:
if elf.colliderect(w):
pick_white = w
# store the original position
x = w.x
y = w.y
elif key == keys.SPACE and pick_white != None:
for square in board:
# shouldnt be able to drop if there is already white piece there
if elf.colliderect(square):
for w in white:
if w != pick_white and square.colliderect(w):
return
# pawns cant move backwards
if pick_white.image == 'chess/pawn-white' and square.y > y:
return
# snap the white piece to the board
pick_white.x = square.x
pick_white.y = square.y
# take the black piece if there
for b in list(black):
if b.colliderect(pick_white):
black.remove(b)
# Queening the Pawn:
# pick_white.image is chess/pawn-white for the white pawn
# set the pick_white.image to chess/queen-white if it reaches the black end of the board
if pick_white.image == 'chess/pawn-white' and pick_white.y == 0:
pick_white.image = 'chess/queen-white'
# drop it
pick_white = None
break
if key == keys.P and pick_black == None:
# pick up the piece below
for b in black:
if king.colliderect(b):
pick_black = b
# store the original position
y = b.y
x = b.x
elif key == keys.P and pick_black != None:
for square in board:
if king.colliderect(square):
# dont allow a drop if there is already a black piece there
for b in black:
if b != pick_black and square.colliderect(b):
return
# pawns cant move backwards
if pick_black.image == 'chess/pawn-black' and square.y < y:
return
# snap the black piece to the board
pick_black.x = square.x
pick_black.y = square.y
# take the white piece if there
for w in list(white):
if w.colliderect(pick_black):
white.remove(w)
# Queen the Pawn
if pick_black.image == 'chess/pawn-black' and pick_black.y == 700:
pick_black.image = 'chess/queen-black'
# drop it
pick_black = None
break
def update():
global pick_white,pick_black
if keyboard.W:
elf.y -= 5
if keyboard.S:
elf.y += 5
if keyboard.A:
elf.x -= 5
if keyboard.D:
elf.x += 5
if keyboard.UP:
king.y -= 5
if keyboard.DOWN:
king.y += 5
if keyboard.LEFT:
king.x -= 5
if keyboard.RIGHT:
king.x += 5
# move the white piece with the elf
if pick_white != None:
pick_white.x = elf.x - 30
pick_white.y = elf.y - 30
# move the black piece with the king
if pick_black != None:
pick_black.x = king.x - 30
pick_black.y = king.y - 30
def draw():
screen.fill('deepskyblue')
for square in board:
square.draw()
for b in black:
b.draw()
for w in white:
w.draw()
elf.draw()
king.draw()
pgzrun.go()
```
[DAY-174] if; list
The knight moves in shape L, so we have to make all other moves illegal.
First draw on a sheet of paper all possible moves, and
There are many ways you can implement this but we will focus on two, one with just if conditions, and one with a list of possible moves.
With if conditions, what we do is we set the move as bad (good = False
), and then we check if it is actually one of the good moves we do good = True
, in the end if its not a good move we return from the on_key_press
function and the piece is not dropped on the square.
```
elif key == keys.P and pick_black != None:
for square in board:
if king.colliderect(square):
...
# knight can only move L shape
if pick_black.image == 'chess/knight-black':
good = False
if square.x == x + 100 and square.y == y - 200:
good = True
elif square.x == x + 100 and square.y == y + 200:
good = True
elif square.x == x - 200 and square.y == y - 100:
good = True
elif square.x == x - 200 and square.y == y + 100:
good = True
elif square.x == x - 100 and square.y == y + 200:
good = True
elif square.x == x + 200 and square.y == y + 100:
good = True
elif square.x == x + 200 and square.y == y - 100:
good = True
elif square.x == x - 100 and square.y == y - 200:
good = True
elif square.x == x and square.y == y:
good = True
if not good:
return
...
```
For the white pieces we will try the other approach, which checks if a the move is in a list of allowed moves. You can check if a list is in a list, e.g. a = [[1,2],[3,4]]
you can just try if [1,2] in a
, so we can simply build a list of possible moves, and check if the square we are dropping the piece on is one of those moves.
```
...
elif key == keys.SPACE and pick_white != None:
for square in board:
# shouldnt be able to drop if there is already white piece there
if elf.colliderect(square):
...
# knight can only move L shape
knight_possible = [
[x,y],
[x+100,y-200],
[x+100,y+200],
[x-200,y-100],
[x-200,y+100],
[x-100,y+200],
[x+200,y+100],
[x+200,y-100],
[x-100,y-200]
]
if pick_white.image == 'chess/knight-white' and [square.x,square.y] not in knight_possible:
return
...
```
[DAY-175] if
The pawn can only move 2 squares from starting position and 1 square otherwise, try to implement this rule by yourself.
this is the code she wrote (including the comment)
```
...
#if pawn.y == 600:
#pawn can only move 200:
#else
#pwan can move only 100
if pick_white.image == 'chess/pawn-white':
if y == 600:
if y - square.y > 200:
return
if y != 600:
if y - square.y >100:
return
...
if pick_black.image == 'chess/pawn-black':
if y == 100:
if square.y - y > 200:
return
if y != 100:
if square.y - y >100:
return
```
[DAY-176] if
First rename x and y to pick_x and pick_y so things are clearer when you compare square.x with pick_x. Then come up with a way to limit the king's movements to only one square.
this is the code she wrote
...
if pick_black.image == 'chess/king-black':
if square.y - pick_y > 100 or square.y - pick_y < -100:
return
if square.x - pick_x > 100 or square.x - pick_x < -100:
return
...
[DAY-177] if
The rook can move only vertically or horizontaly, meaning that either its x or y does not change. Try to code the rule by yourself. If you get stuck, try to do only vertical (x does not change) or horizontal (y does not change), and then think how to add the other direction.
Remember, always try the simple thing first.
this is the code she wrote
...
if pick_black.image == 'chess/rook-black':
if square.x != pick_x and square.y != pick_y:
return
...
[DAY-178] if; absolute
Today we will do the rule for the bishop, since the bishop moves in diagonal. You see in the image that the diagonal means that both x and y change with the same absolute amount, lets say we want to move only one square, the possible values are: -1 -1, -1 1, 1 1, 1 -1, meaning move up and left (decrease y and decrease x), up and right (decrease y, increase x), down and right (increase y, indcrease x), down and left (increase y, decrease x).
Note that if you actually only care if the amount of steps away from the origin, the dirction does not matter. In math when we care about the absolute value of a number we just care about the amount of steps it would take to get from that number to zero, for example from -5 to zero it will take 5 steps, from 5 to zero it will also take 5 steps.
<--------------------|-------------------->
-5 -4 -3 -2 -1 0 1 2 3 4 5
Imagine you walking from -5 to zero, or from 5 to zero both will take you 5 steps. So lets write a function that takes a number and if the number is negative we will just turn it into its positive value, as we only care about the amount of steps.
def abs(x):
if x < 0:
return x * -1
return x
Now lets make the bishop rule. If the steps change in x is the same as the change in y then we must be moving in a diagonal, if not we refuse the move.
```
...
if pick_white.image == 'chess/bishop-white':
# how much did the y change
d_y = pick_y - square.y
# how much did the x change
d_x = pick_x - square.x
# if they didnt change the same amount, then its illegal move
if abs(d_y) != abs(d_x):
return
...
```
[DAY-179] if; for
Today we will do two more rules, one is the queen and one for the pawn. The queen can move like the rook and the bishop combined, so horizontally, vertically and diagonally. The pawn can move one step diagonally if she can take an enemy piece.
Lets start with the queen, as we already have the rook and bishop rules, it is quite easy, we just have to say 'if the move is not like the rook and not like the bishop then its illegal'.
```
if pick_white.image == 'chess/rook-white':
if square.x != pick_x and square.y != pick_y:
return
if pick_white.image == 'chess/bishop-white':
d_y = pick_y - square.y
d_x = pick_x - square.x
if abs(d_y) != abs(d_x):
return
if pick_white.image == 'chess/queen-white':
d_y = pick_y - square.y
d_x = pick_x - square.x
if abs(d_y) != abs(d_x) and square.x != pick_x and square.y != pick_y:
return
...
```
The pawn is a bit more complicated, we need to check if the move is actually one step diagonally, and we also need to have a way to check if a piece is on specific position. We will make is_on_square
function, that takes a position and a list and checks if any of the items of that list is on that position.
```
def is_on_square(x, y, pieces):
for p in pieces:
if p.x == x and p.y == y:
return True
return False
```
Now that we have the is_on_square
function, we can simply check if the y
of the square is exactly on top of the original position, and the x
of the square is either one to the left or one to the right, which would mean either 1 square left diagonal or right diagonal, and then check if there is a black piece there, if it is allow the move.
```
...
if pick_white.image == 'chess/pawn-white':
# 1 or 2 squares
if pick_y == 600:
if pick_y - square.y > 200:
return
if pick_y != 600:
if pick_y - square.y > 100:
return
# pawn can only go left or right if theres someone
if pick_x != square.x:
ok = False
if pick_y - square.y == 100 and pick_x - square.x == 100 and is_on_square(square.x, square.y, black):
ok = True
if pick_y - square.y == 100 and pick_x - square.x == -100 and is_on_square(square.x, square.y, black):
ok = True
if not ok:
return
...
```
[DAY-180] if
There is an important rule in chess, that many people dont know, En Passant (In Passing).
From Wikipedia (https://en.wikipedia.org/wiki/En_passant):
En passant (French: [ɑ̃ paˈsɑ̃], lit. in passing) is a move in chess. It is a special pawn capture that can only occur immediately after a pawn makes a move of two squares from its starting square and provided that it could have been captured by an enemy pawn had it advanced only one square. The opponent captures the just-moved pawn "in passing" through the first square. The result is the same as if the pawn had advanced only one square and the enemy pawn had captured it normally.
The en passant capture must be made on the very next turn or the right to do so is lost. En passant capture is a common theme in chess compositions.
The en passant capture rule was added in the 15th century when the rule that gave pawns an initial double-step move was introduced. It prevents a pawn from using the two-square advance to pass an adjacent enemy pawn without the risk of being captured.
So its pretty nice rule, what we have to do is to remember each pawn that moves two squares and consider it possible en_passant, and then if the oponnent's pawn wants to move diagonally we will check if there is en_passant above(black)/below(white) and if there is we will capture it. If any move is made we will clear the en-passant
the code looks like this:
```
enpassant = None
def on_key_down(key):
global pick_white, pick_black, pick_x, pick_y, enpassant
...
elif key == keys.SPACE and pick_white != None:
for square in board:
# shouldnt be able to drop if there is already white piece there
if elf.colliderect(square):
...
if pick_white.image == 'chess/pawn-white':
# 1 or 2 squares
if pick_y == 600:
if pick_y - square.y == 200:
enpassant = pick_white
if pick_y - square.y > 200:
return
if pick_y != 600:
if pick_y - square.y > 100:
return
# if y > 200 first move:
# pawn can only go left or right if theres someone
if pick_x != square.x:
ok = False
if pick_y - square.y == 100 and pick_x - square.x == 100 and is_on_square(square.x, square.y, black):
ok = True
if pick_y - square.y == 100 and pick_x - square.x == -100 and is_on_square(square.x, square.y, black):
ok = True
if (pick_y - square.y == 100 and pick_x - square.x == 100) or (pick_y - square.y == 100 and pick_x - square.x == -100):
if enpassant != None and enpassant.image == 'chess/pawn-black':
if enpassant.x == square.x and enpassant.y == square.y + 100:
black.remove(enpassant)
ok = True
if not ok:
return
# pawns cant move backwards
if square.y > pick_y:
return
# Queening the Pawn:
# pick_white.image is chess/pawn-white for the white pawn
# set the pick_white.image to chess/queen-white if it reaches the black end of the board
if square.y == 0:
pick_white.image = 'chess/queen-white'
...
# snap the white piece to the board
pick_white.x = square.x
pick_white.y = square.y
if enpassant != pick_white:
enpassant = None
...
```
Notice how we set enpassant = pick_white if the pawn moves 2 squares (this will be used if the black pawn tries to capture), and later when we see that the pawn is moving diagonally we do:
if (pick_y - square.y == 100 and pick_x - square.x == 100) or (pick_y - square.y == 100 and pick_x - square.x == -100):
if enpassant != None and enpassant.image == 'chess/pawn-black':
if enpassant.x == square.x and enpassant.y == square.y + 100:
black.remove(enpassant)
ok = True
This basically checks if it is one square diagonal to the left or one square diagonal to the right, and if it is it checks if there is active enpassant and it is a black pawn, then it checks if it sits directly above the square we want to go to, and if it is we capture it and mark the move valid.
[DAY-181] if
Add undo support. We need to store the piece's position when its picked up, the piece itself and its image (in case of Queening The Pawn) and we need to store those for every move, then if the key 'b' is pressed we need to take the last move and revert it, and so on.
A good strategy for that is to simply use a list, and each time we pick a piece we will append the position_x, position_y, image, actor and then when 'b' is pressed we will pop them out and set them to the actor in question.
```
...
back = []
def on_key_down(key):
global pick_white, pick_black, pick_x, pick_y, pick_image, enpassant,back
if key == keys.SPACE and pick_white == None:
# pick up the piece below
for w in white:
if elf.colliderect(w):
pick_white = w
# store the original position
pick_x = w.x
pick_y = w.y
pick_image = w.image
elif key == keys.SPACE and pick_white != None:
for square in board:
# shouldnt be able to drop if there is already white piece there
if elf.colliderect(square):
# make sure the move is valid
...
back.append(pick_image)
back.append(pick_y)
back.append(pick_x)
back.append(pick_white)
pick_white.x = square.x
pick_white.y = square.y
...
if key == keys.B:
if len(back) != 0:
actor = back.pop()
x = back.pop()
y = back.pop()
image = back.pop()
actor.x = x
actor.y = y
actor.image = image
...
```
We are using the list like a stack, we add stuff to it and when we need we pop the top most items. You can see that we append image, y, x, actor but when we pop we get them in reverse order, because pop() removes the top most item from the ist, so we get back actor, x, y, image.
There is a fundamental limitation to this aproach, which is that we lose pieces that were taken, so if you undo they will just be gone.
[DAY-182] look back
Today we will look back on some of the first programs you wrote.
Open our old files and read as many of them as you can.
[DAY-183] Generalization
From today we will start to think before we code. You can see the game of chess we made, it kind of works but it is quite hard to add things to it, and to add new rules and etc. It is already around 500 lines of hard to read if statements.
We will do one week of exercises without writing code, just with pen and paper, where we will generalize, or try to extract the common attributes of things. We will think about how to think about things.
Lets start with an example. You know that 1 + 2
is the same as 2 + 1
, or 1 + 2 = 2 + 1
, same with 3 + 5 = 5 + 3
, this is quite intuitive, if you have two apples in one hand and one in the other, you have 3 apples irrelevant of which hand has 2 apples and which has 1. We can generalize that rule to a + b = b + a
, meaning that any number a
plus any number b
is the same as wiriting b+a
. It might seem like we did nothing here, just stated the obvious, but I will show you how powerful this generalization is.
At first we were thinkging of numbers, but with this generalization we can actually use expressions, for example a = ((4838 + 8272) * 3)
and b = ((7467 / 2) + 27838)
and still a + b = b + a
, we can substitute a
and b
, so ((4838 + 8272) * 3) + ((7467 / 2) + 27838) = ((7467 / 2) + 27838) + ((4838 + 8272) * 3)
. We have higher level of reason, we are not confined to numbers anymore, but to whole expressions and expressions of expressions.
Lets talk now about what is needed to represent a chess piece. First we need its color, is it black or white, we need its kind (rook, bishop etc..), and its position x and y. Those are the properties of a piece. Each piece however can move in a different way, this is its behavior. Those are the two main things we have to think about, we can generalize thenm into 'what does the thing do' and 'how does the thing look'.
This week we will spend more time on examples about generalization and abstraction, and after that we will rewrite the chess game. It is very common to write something quick, and then rewrite it when you know how to actually think about it. The first time you code something is almost never good, purely because you still dont know how to represent the things in your program yet, even if you think a lot about it. In the real world you need to combine the both aproaches, of code and explore, and think carefully about how the pieces in your program talk to each other.
[DAY-184] Generalization
We (me and my daughter) have spent 30 minutes per day for the last week just talking about how to think about behavior and state. With all kinds of discussions, from tic tac toe, to stratego, to classess and lists and many more concepts. The talks were very open and unstructured, so it is hard to put them directly 1:1 in the book. I recommend you do the same. Spend time talking about how to think about your program, how the parts in it communicate, how you group the state, and how do you abstract behaviour. It is also important to think about how to think about problems in general, move one layer above practicality. Discuss patterns.
[DAY-185] Generalization
Today we will build three different versions of snakes and ladders to illustrate different approaches.
We will use super small Snakes and Ladders game with the following rules:
there are 9 squares, from 0 to 8
0 -> 0
1 -> 2
2 -> 2
3 -> 3
4 -> 2
5 -> 7
6 -> 0
7 -> 7
8 -> 8
While and If, most basic implementation. In this implementation if we do 99 squares or we want to render a board, or we want to make the game more interesting to roll the dice twice or something like that, everything will just explode in complexity.
```
player1 = 0
while True:
print("player board position: ", player1)
dice = int(input("dice roll> "))
player1 += dice
if player1 == 1:
player1 = 3
elif player1 == 4:
player1 = 2
elif player1 == 5:
player1 = 7
elif player1 == 6:
player1 = 0
```
Think about the rules of the game and what is a bit more abstract way to think about the them. The only rule actually is: if you land on the square you move wherever the square says, could be 0 (stay there), +steps or -steps. This is an example implementation where we just keep the state of each square in a list, square index 1 moves you to index 3 and so on.
```
board = [
0,
2, # 1 -> 3
0,
0,
-2, # 4 -> 2
2, # 5 -> 7
-6, # 6 -> 0
0,
0
]
player1 = 8
while True:
print("player board index: ", player1)
dice = int(input("dice roll> "))
player1 += dice
if player1 >= len(board) - 1:
print("finished")
break
snake_or_ladder = board[player1]
player1 += snake_or_ladder
```
The whole game is actually encoded in those two lines:
snake_or_ladder = board[player1]
player1 += snake_or_ladder
See how different this is? The size of the code is very similar in lines, but this version is so much easier to change and to extend. For example if we want to display the board, now we can just pass the board list to some render
function and be done. This is actually not possible in the first version with the if conditions unless we almost duplicate the whole program.
There is one more thing we could do to simplify it a bit, and that is to split the board from the input. So that we could move it maybe in a separate file (board.py) if we want. Separating the user input from the board action is quite nice because now it will be super easy to add mouse click functionality, and board rendering.
```
class Board:
def init (self):
self.player = 0
self.squares = [
0,
2, # 1 -> 3
0,
0,
-2, # 4 -> 2
2, # 5 -> 7
-6, # 6 -> 0
0,
0
]
def move(self, dice):
position = self.player + dice
if position >= len(self.squares) - 1:
return True
self.player += self.squares[position]
return False
b = Board()
while True:
print("player board position: ", b.player)
roll = int(input("dice roll> "))
if b.move(roll):
print('finished')
break
```
[DAY-186] If
Make snakes and ladders on your own with pygame zero.
This is what she wrote. She just went and found 500x500 board so that its easy to compute the position of each square, and hardcoded the jumps.
```
import pgzrun
import random
HEIGHT = 500
WIDTH = 500
elf = Actor("c1")
elf.x = -25
elf.y = 475
game_over = False
board = Actor("snake-500")
def on_key_down(key):
if key == keys.SPACE:
elf.x += random.choice([50,100,150,200,250,300])
if elf.x > 475 and elf.y == 25:
elf.x = 25
elf.y = 25
if elf.x > 475:
elf.x -= 500
elf.y -= 50
if elf.y == 375 and elf.x == 225:
elf.y = 475
elf.x = 225
if elf.y == 25 and elf.x == 25:
elf.y = 175
if elf.y == 475 and elf.x == 125:
elf.y = 225
elf.x = 25
if elf.y == 325 and elf.x == 175:
elf.y = 475
elf.x = 25
if elf.y == 475 and elf.x == 275:
elf.y = 375
elf.x = 325
if elf.y == 175 and elf.x == 125:
elf.y = 25
elf.x = 225
if elf.y == 75 and elf.x == 325:
elf.y = 225
elf.x = 325
if elf.y == 25 and elf.x == 425:
elf.y = 175
elf.x = 425
if elf.y == 475 and elf.x == 425:
elf.y = 175
elf.x = 425
def update():
global game_over
speed = 10
if keyboard.UP:
elf.y -= speed
if keyboard.DOWN:
elf.y += speed
if keyboard.LEFT:
elf.x -= speed
if keyboard.RIGHT:
elf.x += speed
if elf.x == 475 and elf.y == 25:
game_over = True
def draw():
board.draw()
elf.draw()
if game_over == True:
screen.draw.text('YOU WIN CONGRATULATION',(100,100),color = (0,0,0))
pgzrun.go()
```
she also made a grid to compute the positions of each square
[DAY-187] If; While; Functions
Watch Programming for Advanced Beginners: Battleships - EP 1, from Robert Heaton (https://www.youtube.com/watch?v=Gi0Fdyhk1_0), and then watch it again and code with the author
[DAY-188] OOP
Watch https://www.youtube.com/watch?v=JeznW_7DlB0 (Python Object Oriented Programming (OOP) - For Beginners
from Tech With Tim)
[DAY-189] Keyword Arguments; String Methods
Today you have to watch three videos:
Python keyword arguments 🔑 by Bro Code - https://www.youtube.com/watch?v=Tu0lFBXQgPw
Python string methods by Bro Code - https://www.youtube.com/watch?v=crw3rVFNwIM
Python Object Oriented Programming (OOP) - For Beginners from Tech With Tim - https://www.youtube.com/watch?v=JeznW_7DlB0 (watch it again)
[DAY-190] While
Make a web whatsapp bot that sends the same message in an infinite loop
click on the chrome tab with whatsapp
click on the search box
searche for contact name (dad)
clicks on the top result
click on the message input field
type 'hello world'
click the send button
Using https://pyautogui.readthedocs.io/en/latest/ as a guide. There are many ways to read documentation, try to spend some time just brawsing through it. Another way is to go to the example section and see if you can find examples that can help you solve your problem.
This is a snippet with examples taken from pyautogui's page:
```
import pyautogui
screenWidth, screenHeight = pyautogui.size() # Get the size of the primary monitor.
screenWidth, screenHeight
(2560, 1440)
currentMouseX, currentMouseY = pyautogui.position() # Get the XY position of the mouse.
currentMouseX, currentMouseY
(1314, 345)
pyautogui.moveTo(100, 150) # Move the mouse to XY coordinates.
pyautogui.click() # Click the mouse.
pyautogui.click(100, 200) # Move the mouse to XY coordinates and click it.
pyautogui.click('button.png') # Find where button.png appears on the screen and click it.
pyautogui.move(400, 0) # Move the mouse 400 pixels to the right of its current position.
pyautogui.doubleClick() # Double click the mouse.
pyautogui.moveTo(500, 500, duration=2, tween=pyautogui.easeInOutQuad) # Use tweening/easing function to move mouse over 2 seconds.
pyautogui.write('Hello world!', interval=0.25) # type with quarter-second pause in between each key
pyautogui.press('esc') # Press the Esc key. All key names are in pyautogui.KEY_NAMES
with pyautogui.hold('shift'): # Press the Shift key down and hold it.
pyautogui.press(['left', 'left', 'left', 'left']) # Press the left arrow key 4 times.
Shift key is released automatically.
pyautogui.hotkey('ctrl', 'c') # Press the Ctrl-C hotkey combination.
pyautogui.alert('This is the message to display.') # Make an alert box appear and pause the program until OK is clicked.
```
use pyautogui.position()
to find the accurate positions for your screen.
import pyautogui
import time
while True:
pyautogui.click(305,10)
pyautogui.click(117,252)
pyautogui.write('dad', interval=0.25)
pyautogui.click(185, 395)
pyautogui.write('hello world!', interval=0.20)
pyautogui.click(935, 1132)
time.sleep(1)
Have some fun with it pranking your parents :) but not too much .
[DAY-191] While
Make another whatsapp bot, but this time send a very very long message.
```
import pyautogui
import time
import random
while True:
pyautogui.click(305,10)
pyautogui.click(117,252)
pyautogui.write('dad', interval=0.25)
time.sleep(1)
pyautogui.click(185, 395)
time.sleep(1)
for i in range(3000):
s = 'yo' * random.randint(1, 4)
pyautogui.write(s + ' ')
time.sleep(5)
pyautogui.click(935, 1132)
```
this will send the message:
"yoyoyo yoyoyo yoyoyo yoyoyoyo yo yo yoyoyo yoyoyo yoyoyoyo yo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyo yo yo yoyo yoyo yo yoyo yoyo yo yoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yoyoyoyo yoyoyo yo yoyoyoyo yo yoyoyo yoyo yoyoyo yoyo yo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yo yoyoyo yoyoyo yoyoyoyo yoyo yoyo yo yoyo yoyoyo yoyoyoyo yoyo yo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yo yo yo yoyo yo yoyoyo yoyo yoyoyo yoyo yoyoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyo yo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yo yoyoyo yoyoyoyo yoyo yo yoyoyo yoyo yoyo yoyo yo yo yoyo yoyoyoyo yo yoyo yo yoyoyo yo yoyoyo yoyoyoyo yoyoyo yoyo yoyo yo yoyoyoyo yo yoyo yo yoyoyoyo yoyoyo yo yoyoyoyo yoyo yoyo yoyoyo yoyoyo yoyo yo yo yoyoyoyo yoyo yo yoyoyoyo yoyoyoyo yoyo yoyo yoyo yo yoyoyo yoyoyoyo yoyo yoyoyo yoyo yoyo yo yoyoyoyo yo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyo yoyo yoyoyo yoyo yoyo yoyo yoyo yo yo yoyo yoyo yo yoyo yoyo yoyoyo yoyo yo yo yoyoyoyo yo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyo yoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yo yoyoyo yo yoyoyo yoyoyoyo yo yo yoyoyo yoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yo yoyoyoyo yoyo yo yoyoyoyo yoyo yoyo yo yo yoyoyo yo yo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyo yoyo yo yo yoyoyoyo yoyo yoyo yoyoyo yoyo yo yoyoyoyo yoyo yoyo yoyoyo yoyoyo yoyoyoyo yo yoyoyo yoyoyo yoyo yo yoyoyoyo yoyo yoyoyoyo yoyo yo yoyoyoyo yoyo yoyo yoyoyo yoyoyo yoyoyo yo yo yoyoyo yoyoyo yoyoyoyo yo yo yo yoyoyo yoyo yoyo yoyoyo yoyo yo yoyoyoyo yoyoyoyo yoyo yoyo yoyoyo yo yoyoyoyo yo yo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyo yo yo yoyo yoyoyoyo yo yo yoyoyo yo yoyoyo yoyoyoyo yo yoyo yoyoyo yoyo yoyoyo yo yo yoyoyo yoyoyoyo yo yo yoyoyo yoyo yoyoyoyo yo yoyo yoyo yoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyo yo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yo yo yoyoyoyo yoyoyoyo yoyo yo yoyo yoyo yo yoyoyo yoyoyo yoyoyoyo yo yoyoyo yoyo yoyoyoyo yo yoyo yo yoyo yoyoyoyo yo yoyoyo yoyo yoyo yoyoyo yoyoyoyo yo yo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyo yoyo yo yo yo yoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyoyo yo yoyoyo yo yo yoyo yo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yo yo yoyoyo yo yoyo yoyoyo yoyo yoyoyo yoyo yo yoyo yo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yo yoyo yoyo yoyoyoyo yoyo yoyoyoyo yoyo yoyo yoyoyoyo yoyo yo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyo yo yoyo yo yoyo yo yoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yo yoyo yo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyo yo yoyoyo yoyoyo yoyo yoyo yoyo yoyo yo yoyo yoyo yoyoyo yoyoyo yoyoyoyo yoyo yo yo yoyo yo yoyoyoyo yo yoyoyoyo yoyoyo yoyo yoyoyo yoyo yoyoyo yoyoyo yoyoyo yo yo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyo yoyo yo yoyo yo yoyoyo yo yoyoyo yo yoyoyoyo yoyo yo yoyo yoyo yoyoyo yoyoyo yo yo yoyoyoyo yoyo yo yo yoyoyo yo yo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyo yo yoyoyo yoyoyoyo yoyoyoyo yo yo yo yoyoyo yo yoyo yoyo yoyoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yo yoyoyoyo yo yoyoyo yo yoyoyo yoyoyoyo yoyo yo yoyo yoyoyo yoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyoyo yoyo yoyoyo yoyo yoyoyo yoyoyo yo yo yoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyo yoyo yo yoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyo yo yoyoyoyo yoyo yoyoyoyo yo yo yoyoyoyo yoyoyoyo yoyoyo yo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyo yoyo yoyo yo yoyoyo yoyoyo yo yoyoyoyo yo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyo yoyoyo yo yoyo yoyo yoyo yoyo yoyoyoyo yoyo yo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyo yo yoyo yo yoyoyo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyoyo yo yoyo yoyoyoyo yo yoyoyo yoyoyo yoyoyoyo yoyo yoyoyo yoyo yo yoyo yoyoyo yo yoyo yo yo yoyoyo yo yo yoyoyoyo yoyoyoyo yoyo yoyo yoyoyoyo yoyo yoyo yoyoyo yoyo yoyoyo yoyo yo yoyoyoyo yoyoyo yo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyo yo yoyoyoyo yoyoyo yoyo yo yoyo yo yoyoyo yo yoyoyo yo yoyoyoyo yoyoyo yo yo yoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyo yo yoyoyo yoyoyo yoyo yoyo yoyoyoyo yo yoyo yoyo yoyo yoyo yoyoyoyo yoyo yoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyo yo yoyo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyo yoyoyoyo yo yoyoyoyo yoyo yoyo yoyoyoyo yoyo yo yo yoyo yo yoyo yo yoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yo yo yoyoyoyo yoyo yoyoyo yoyo yoyo yoyoyoyo yo yoyo yoyo yoyo yoyoyoyo yo yo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yoyo yoyoyo yoyoyoyo yoyoyo yo yoyo yo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyoyoyo yoyo yo yoyo yoyoyo yoyoyoyo yoyo yoyoyo yo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyoyo yoyo yo yoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yo yoyoyo yoyoyo yoyo yoyoyo yoyo yoyo yoyoyo yo yoyo yoyoyo yoyo yoyoyo yoyo yoyoyo yoyoyo yo yoyoyo yoyo yoyo yoyoyo yoyoyoyo yoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yo yo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyo yo yoyoyo yo yoyo yoyoyo yoyo yoyo yo yoyoyoyo yoyoyoyo yo yoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yo yoyo yoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yo yoyo yoyoyoyo yoyo yo yoyo yoyoyoyo yoyoyo yo yoyoyoyo yoyoyo yoyo yo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyo yoyoyo yoyo yo yoyoyo yo yoyoyoyo yoyoyoyo yoyo yoyo yoyoyo yo yoyoyo yoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yo yo yo yoyo yoyoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yo yoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yo yo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyo yo yoyoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyo yo yo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yo yoyo yoyo yo yoyoyoyo yoyo yoyo yoyo yoyo yo yoyo yo yoyoyo yoyoyo yoyo yo yo yoyoyoyo yo yoyoyoyo yoyoyo yoyo yoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yo yoyo yoyoyoyo yoyo yoyoyo yoyoyoyo yoyo yoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyo yo yoyoyo yoyoyoyo yoyoyoyo yo yoyo yo yo yo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyo yoyo yo yoyo yo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yo yoyo yoyoyoyo yoyo yoyoyo yo yoyoyo yo yoyo yoyoyoyo yoyoyo yo yoyoyo yo yoyoyoyo yo yoyo yoyoyo yoyo yoyoyo yo yo yo yo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yo yo yoyo yoyoyoyo yoyoyo yo yoyo yoyo yo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yo yo yoyo yoyoyo yoyo yoyoyoyo yo yoyoyo yoyo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyo yoyoyo yo yo yoyoyo yoyoyoyo yoyo yoyoyoyo yo yoyo yo yoyoyoyo yoyoyo yoyoyo yo yo yoyo yoyoyo yoyoyo yoyo yoyoyo yoyo yoyoyoyo yoyoyo yoyo yo yo yoyo yoyo yoyo yoyoyoyo yo yoyoyoyo yoyo yoyoyoyo yo yoyoyo yoyo yoyoyo yoyoyoyo yo yo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yo yo yoyoyoyo yoyo yo yoyo yoyo yoyo yoyoyoyo yo yoyo yo yo yoyoyoyo yoyo yoyo yoyoyoyo yoyo yoyoyo yo yo yo yoyo yo yoyoyoyo yoyo yoyo yoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyoyo yoyo yoyo yoyo yoyoyo yoyoyoyo yo yoyoyo yoyoyo yo yoyo yoyo yoyoyo yo yo yoyo yoyo yo yoyo yoyoyo yo yoyoyoyo yoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yo yo yoyoyo yo yoyoyoyo yoyo yoyoyoyo yoyoyo yo yoyoyoyo yo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyo yoyo yo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyoyo yo yoyoyoyo yo yoyoyo yoyo yoyo yoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyoyo yoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyo yoyoyo yo yoyoyoyo yoyoyo yoyo yoyoyo yo yo yoyoyo yoyoyo yoyo yoyoyoyo yoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yo yoyo yoyo yoyoyoyo yo yoyoyo yoyoyo yo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yo yoyo yoyoyoyo yo yo yoyoyoyo yoyo yoyo yoyoyo yoyo yoyo yoyo yo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyo yo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yo yo yoyoyo yoyo yo yoyo yo yoyoyo yo yoyoyo yoyoyo yoyo yoyo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyo yoyo yoyo yoyoyoyo yoyo yoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyo yo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyo yoyoyo yoyoyoyo yo yo yo yo yoyoyoyo yoyoyo yoyo yoyo yo yoyoyo yoyoyoyo yoyo yoyo yoyo yoyo yoyoyo yoyoyo yoyoyo yo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yo yo yoyoyoyo yo yoyoyo yoyo yoyoyo yoyo yoyo yoyo yo yoyo yoyoyo yo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyoyo yo yo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyo yo yo yoyoyo yo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yo yo yoyoyo yoyoyoyo yoyoyo yoyo yo yoyoyo yoyoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyo yo yoyoyoyo yo yoyoyo yoyo yoyoyo yo yoyoyoyo yo yo yo yoyoyo yo yo yoyo yoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyo yoyo yo yo yoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yo yo yo yo yo yoyo yo yo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yo yo yoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyo yoyoyoyo yoyoyoyo yoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyo yo yo yo yoyoyoyo yoyoyoyo yo yo yoyo yo yoyo yoyoyo yoyoyo yoyo yoyoyo yo yoyoyo yoyoyo yoyoyoyo yo yo yoyo yoyoyoyo yo yoyoyoyo yoyo yoyo yo yoyoyoyo yo yo yoyoyoyo yoyo yo yoyoyoyo yo yoyoyo yo yo yoyoyo yoyoyoyo yoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyo yoyo yoyo yo yo yoyoyoyo yoyoyo yoyo yoyo yo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yoyo yoyoyo yoyoyoyo yoyo yoyo yo yoyoyo yoyoyo yo yoyoyo yo yoyoyo yo yo yoyoyoyo yo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyoyo yoyoyo yo yo yoyo yoyo yoyoyo yoyoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyoyo yoyoyo yo yoyo yoyo yoyoyoyo yo yoyoyo yoyoyo yoyoyoyo yoyo yoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyo yoyoyo yo yoyo yoyoyoyo yoyoyo yo yoyo yoyoyo yoyoyoyo yo yoyoyo yoyoyo yo yo yoyo yoyoyoyo yo yoyoyoyo yo yoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yo yoyo yo yoyoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyo yoyoyo yo yoyo yoyoyoyo yo yoyo yoyo yoyoyoyo yoyo yoyoyoyo yo yoyoyoyo yoyo yo yo yoyoyoyo yoyoyoyo yoyo yoyo yoyo yoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyoyo yo yoyoyoyo yo yoyo yoyoyo yo yoyo yoyoyo yo yo yoyoyoyo yo yoyo yoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyoyo yoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yoyoyo yo yoyoyo yo yoyoyoyo yo yoyoyo yoyoyoyo yoyo yoyoyo yoyo yoyo yoyo yo yo yoyoyo yoyoyo yoyoyoyo yoyo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyo yo yoyoyo yoyo yoyo yoyo yoyo yoyoyoyo yo yoyoyoyo yo yoyoyoyo yoyo yo yoyo yoyoyoyo yoyo yo yoyoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yo yo yoyoyo yoyoyo yo yoyo yoyo yoyoyoyo yo yoyo yoyo yoyoyo yoyoyoyo yo yo yoyoyo yo yoyoyo yoyoyoyo yoyo yoyoyo yoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyo yoyo yo yoyoyoyo yoyoyoyo yoyo yoyo yoyo yoyo yoyoyo yoyoyo yoyo yo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yo yo yoyoyo yoyoyo yo yoyoyoyo yoyoyoyo yoyo yo yoyo yo yoyoyoyo yo yoyoyoyo yo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyo yoyo yo yoyoyo yoyoyoyo yoyo yoyoyo yo yo yoyoyo yo yoyoyoyo yoyoyoyo yo yo yoyoyoyo yoyoyoyo yo yoyo yoyo yo yoyo yo yoyoyoyo yoyo yo yoyoyo yoyoyoyo ypoyoyo yoyoyo yo yoyo yo yoyoyo yoyoyoyo yo yoyo yoyoyo yoyoyo yoyo yoyo yo yoyoyo yoyoyoyo yo yoyo yo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yo yoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yoyo yo yoyoyoyo yoyo yoyoyo yoyo yoyo yo yoyoyoyo yoyo yoyoyo yoyo yo yoyoyo yoyoyoyo yo yoyo yoyoyoyo yo yo yoyoyo yoyo yoyo yo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yo yoyo yo yoyo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyo yoyo yo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yo yoyo yoyoyo yo yoyoyo yoyoyo yoyo yoyoyoyo yoyo yo yoyo yoyoyoyo yoyo yo yoyoyoyo yoyo yoyo yo yoyoyo yo yoyoyoyo yoyo yoyoyo yoyoyoyo yoyo yo yoyoyo yo yoyoyo yoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyo yo yoyoyoyo yoyo yoyo yoyoyo yoyoyo yo yoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyo yoyoyoyo yoyoyo yo yoyo yo yoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyo yoyo yo yo yo yoyoyo yoyoyo yoyoyo yoyo yoyoyoyo yo yoyo yoyoyo yo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyo yo yoyo yoyoyoyo yo yo yoyoyo yoyoyo yoyoyo yo yo yo yoyoyo yoyoyoyo yoyo yoyo yoyoyo yoyoyoyo yoyo yoyo yoyoyo yoyoyo yo yoyoyoyo yo yo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyoyo yo yoyo yoyoyo yo yoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyo yo yoyoyo yoyoyoyo yoyo yoyoyo yo yoyoyoyo yoyo yo yoyoyoyo yo yoyoyoyo yo yoyoyoyo yo yo yoyoyo yoyoyo yoyoyoyo yo yoyoyo yoyoyo yo yoyoyoyo yoyoyo yoyoyo yo yoyoyo yoyoyo yoyo yoyo yo yo yoyoyo yoyo yoyoyo yoyo yo yoyoyoyo yo yoyoyo yo yo yoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyo yoyoyo yo yoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyo yoyo yoyoyo yoyoyo yo yoyoyo yoyo yo yoyoyoyo yoyo yoyoyo yoyo yo yoyoyoyo yoyo yoyo yo yoyoyoyo yo yoyoyo yoyoyo yoyoyo yoyo yoyoyoyo yoyo yoyoyo yoyoyo yoyo yo yoyoyoyo yoyoyo yoyo yoyoyoyo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yo yoyo yoyoyoyo yoyoyoyo yo yoyoyo yoyoyo yo yoyo yoyo yoyoyo yo yoyo yoyoyo yoyoyo yoyo yoyo yoyoyoyo yo yoyoyoyo yo yoyo yoyoyo yo yoyoyo yo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyo yo yoyoyoyo yoyo yo yoyo yoyo yoyoyoyo yoyoyo yoyo yo yoyo yoyo yoyo yoyoyo yoyoyoyo yoyoyo yoyo yoyo yoyoyo yo yoyoyoyo yoyoyo yo yoyoyoyo yoyoyo yoyoyoyo yo yo yoyoyoyo yo yo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyoyo yo yoyoyo yoyoyo yoyoyoyo yoyo yoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyo yo yoyoyo yo yoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyoyo yo yoyoyo yoyoyoyo yoyo yo yoyoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yo yoyoyoyo yoyoyo yo yoyoyoyo yo yoyo yoyoyoyo yo yoyo yoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyo yo yoyoyo yoyoyo yo yoyoyo yoyoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyo yoyoyo yo yoyoyoyo yoyoyo yo yoyoyoyo yoyoyoyo yoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yo yo yoyoyo yoyoyoyo yoyoyoyo yo yoyo yoyoyoyo yoyo yoyoyo yoyoyo yo yo yoyoyoyo yo yoyoyoyo yo yoyo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyo yoyo yoyo yoyo yoyoyo yoyoyo yoyo yoyo yoyoyoyo yo yoyo yo yoyo yo yo yo yoyo yo yoyoyoyo yo yoyoyo yoyoyoyo yo yoyoyo yoyo yoyoyoyo yoyoyo yoyoyo yo yoyoyoyo yo yoyoyoyo yoyoyoyo yo yo yoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyo yo yoyoyoyo yoyo yo yo yoyo yoyoyoyo yoyoyoyo yo yo yoyoyo yoyoyoyo yo yoyoyoyo yo yoyo yoyoyo yoyoyoyo yoyoyo yoyo yoyo yo yo yo yoyoyoyo yoyoyo yoyo yoyo yoyoyo yoyoyo yoyoyo yoyo yo yo yoyoyo yoyo yo yoyoyoyo yoyoyoyo yoyoyo yo yo yoyoyoyo yo yoyoyo yoyoyo yoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyo yoyoyoyo yo yoyoyoyo yoyoyo yo yoyo yoyo yo yoyo yoyoyoyo yo yoyo yo yoyo yoyoyoyo yoyoyoyo yo yo yoyoyo yo yoyoyo yoyo yoyoyoyo yoyo yoyo yo yoyo yo yoyo yoyoyoyo yo yoyoyo yo yoyoyoyo yo yoyoyoyo yo yo yoyo yoyoyoyo yo yo yo yoyoyo yo yo yoyo yoyo yoyoyo yoyo yo yoyoyo yo yoyo yoyoyoyo yoyo yo yoyoyo yoyoyo yoyo yoyo yoyoyo yo yoyo yo yoyo yoyoyo yoyoyo yoyoyoyo yoyo yo yoyoyoyo yo yoyoyo yo yoyoyo yo yoyoyoyo yoyo yoyo yoyoyo yoyo yoyoyo yoyoyoyo yo yoyo yo yo yoyoyoyo yoyoyo yoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yo yoyoyo yo yoyoyo yo yoyoyoyo yoyo yo yo yoyoyo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yo yoyoyoyo yo yo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyo yoyoyo yoyoyo yoyo yoyoyo yoyoyo yoyo yo yo yoyo yoyoyoyo yoyoyoyo yoyo yoyo yoyo yo yoyoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyoyoyo yoyoyo yoyo yo yo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yoyo yoyoyo yoyo yo yoyoyoyo yo yoyoyoyo yoyoyo yoyo yoyo yoyoyoyo yoyoyoyo yoyoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyoyo yoyoyo yoyoyoyo yo yoyoyo yoyoyoyo yo yoyo yoyo yoyo yoyoyo yoyoyoyo yoyoyoyo yoyoyo yo yoyoyoyo yoyo yoyoyo yoyo yoyoyo yoyo yo yoyo yoyo yo yo yoyoyoyo yoyo yoyoyoyo yoyoyo yoyoyo yoyo yo yoyoyo yoyoyoyo yo yoyoyo yoyo yoyoyo yoyo yoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yoyoyo yoyoyoyo yoyoyoyo yoyo yoyoyo yoyo yo yo yo yoyoyoyo yoyo yo yo yoyoyoyo yoyoyo yoyoyoyo yoyo yoyoyoyo yoyo yo yoyoyoyo yoyoyoyo yoyoyo yoyoyo yo yoyoyoyo yoyo yoyo yoyoyo yoyo yoyoyo yoyoyoyo yoyo yoyo yoyoyoyo yo yo yoyoyo yoyo yoyo yoyo yoyoyoyo yoyo yoyo yoyoyoyo yoyo yoyoyo yoyoyoyo yoyoyo yoyoyo yoyoyoyo yoyo yoyoyoyo yo yo yoyoyoyo yoyo yoyo yoyo yo yoyoyoyo yo yoyo yoyoyoyo yo yoyo yoyoyo yoyoyo yoyoyo"