1 of 75

Join our Slack Channel

Slack: https://bit.ly/uwcoffeencodeslack

Channel Name: #war-game

#space-comp for JavaScript

2 of 75

Algorithmic War Game

An introduction to intermediate-level Python

3 of 75

Introductions

4 of 75

Personal Introduction

Hi, my name is Kevin Bacabac.

  • Studying 3B Computer Science
  • I like Python
  • Second time project lead
  • Game developer as a hobby

5 of 75

Who is in this Room? “So tell me about yourself”

  • How many aren’t in Math/Engineering?
  • How many people in here confident with Python or another language?
  • Anyone in Astronomy or Physics?
  • What’s your worst Python install story

6 of 75

Why Python?

  • Commonly used
  • Clean syntax
  • Faster! (in terms of your own time)
  • Gateway to machine learning
  • Backend web development
  • Useful “glue code”
  • Co-op jobs

7 of 75

Project Information

  • We will only be running on Thursdays
    • But there is a “twin project” on Wednesday for JavaScript
  • We assume you have basic programming capabilities:
    • Declaring variables
    • If/Else Statements
    • For and while loops
    • Writing simple functions

^ We’ll review all of these in the first 20 minutes

8 of 75

Project Information

  • Object-oriented programming, List comprehension, Sets, etc
  • Standard Python Package (Typing, Enums, etc)
  • Special methods, decorators, fancy stuff

9 of 75

Project Information (Why?)

  • Object-oriented programming
    • Lets us reuse code
    • Similar to functions but another way of thinking
    • Dangerous and powerful tool
  • Standard Python Package (Typing, Enums, etc)
    • A collection of functions, classes, and other tools that were premade for you

10 of 75

Project Information

  • Reading API Docs and Git
  • PEP8 Styling and industry quality code practices
    • Eliminating redundancy
    • Clean and organized code
  • Why learn to use an API?
    • Your program can “talk to” a service

11 of 75

Project Schedule

  • Lesson 1
    • Python and setup
  • Lesson 2
    • Python and programming together (50 / 50)
  • Lesson 3
    • Python and programming custom bots together (30 / 70)
  • Lesson 4
    • Git and programming (30 / 70)

12 of 75

Project Schedule

  • Lesson 5 / 6
    • Continue working on bots and small competitions
    • Optional advanced Python modules like hacking the game (but won’t be allowed for competitive matches)
      • Maybe special competitions?

We’ll end off spending almost all time programming since writing code is the best way to learn.

13 of 75

Let’s get started

14 of 75

Python Installation

15 of 75

Pygame Installation

  • Open a command line or terminal
  • pip3 install --user pygame (may try pip instead of pip3)
  • Can be quite difficult, ask for help on Slack or look up a guide to pip
  • Common Windows issues
    • pip not found (try to reinstall Python but make sure it adds itself to PATH)
    • Having pre-existing installs

16 of 75

Good luck...

https://xkcd.com/1987/

Use this to practice code snippets if you don’t have Python.

https://repl.it/

17 of 75

Git Install (Optional) for Windows

https://git-scm.com/downloads

18 of 75

Introduction to Git

  • If you downloaded Git you can clone our repository at https://github.com/UWCoffeeNCode/Lessons
  • Or you can download a zip file to get started
    • We’ll cover Git much later after we’ve covered more Python
    • Don’t worry about downloading for now

19 of 75

Let’s get started

20 of 75

Intro to the War Game

21 of 75

War Game Bots

def action(self, country_status: dict, world_state: dict):

weapon = choice(list(Weapons))

if world_state["alive_players"]:

target = choice(tuple(world_state["alive_players"]))

return {

"Weapon": weapon,

"Target": target

}

return {}

22 of 75

War Game Bots Continued

Bot | Wins | Perc

None | 695 | 33%

Smart Bot | 534 | 25%

Lazy Bot | 289 | 14%

Ping Bot | 280 | 13%

Sample Bot | 112 | 5%

Greedy Bot | 98 | 5%

Class Bot | 92 | 4%

23 of 75

The War Game

24 of 75

Reviewing our Python

Table of Contents�- Variables and types

- If, else if, else syntax

- Operations, + - / * %

- Boolean operations, and, or, not

- Avoiding nested ifs

- For / while loops

- Functions

25 of 75

Variables

  • Different types of variables
    • int
    • str
    • float
  • Examples

>>> a = 3

>>> b = "3"

>>> c = 3.0

IDLE Output

>>> a

3

>>> b

'3'

>>> c

3.0

26 of 75

Variables

  • Different types of variables
    • int
    • str
    • float
  • Examples

>>> a = 3

>>> b = "3"

>>> c = 3.0

Addition

>>> a + a

6

>>> c + c

6.0

>>> b + b

'33'

27 of 75

Variables

  • Different types of variables
    • int
    • str
    • float
  • Examples

>>> a = 3

>>> b = "3"

>>> c = 3.0

Guess the output

>>> a * a

9

>>> b * b

Traceback (most recent call last):

b * b

TypeError: can't multiply sequence by non-int of type 'str'

28 of 75

Preview to Casting

  • How do we fix b * b?
  • Use casting to change types

>>> d = int(b)

>>> d

3

>>> d * d

9

str(x), float(x), list(x), tuple(x), int(x), etc

Guess the output

>>> a * a

9

>>> b * b

Traceback (most recent call last):

b * b

TypeError: can't multiply sequence by non-int of type 'str'

29 of 75

Conditions

>>> if True:

print("A")

else:

print("B")

>>> if False:

print("A")

else:

print("B")

>>> if True:

print("A")

elif True:

print("B")

else:

print("C")

Answers: A, B, A

30 of 75

Conditions Summary

  • if statement required to use elif and else
  • elif and else are optional
  • elif only runs when the if or elif above was not run
  • else runs if none of the if or elif has run

31 of 75

Operations

  • +, -, *, /
  • % (modulo)
    • Returns int
  • == and != (equality checks)
    • Returns true or false

Modulo Examples��>>> 7 % 2

1

>>> -7 % 3

2

32 of 75

Equality + Conditions

>>> if 1 == 1:

print("nothing")

elif True:

print("interview")

>>> if 1 == “1”:

print("snowday")

elif True:

print("midterm")

>>> if 1 == 2:

print("marks")

elif 1 == “1”:

print("passing")

Answers: nothing, midterm, [literally nothing]

33 of 75

Boolean Operations (Case sensitive!)

  • Require two booleans (on left and right)
  • and
    • True and True == True
    • True and False == False
    • Both must be true
  • or
    • True or True == True
    • True or False == True
    • One must be true

  • not
    • Requires just one boolean
    • not True == False
    • not False == True
  • xor (extra)
    • A != B
    • True != False == True
    • True != True == False

34 of 75

Boolean Operations

What do we do with a nested if?

if handwashing:

if sleeping_well:

print("no corona")

Try boolean operations

if handwashing and sleeping_well:

print("no corona")

35 of 75

Loops - While

A = 0

if A < 2:

A = A + 1

if A < 2:

A = A + 1

if A < 2:

A = A + 1

...

A = 0

while A < 2:

A = A + 1

36 of 75

Loops - While

  • Why while loops

while True:

time.sleep(1)

if condition:

pass # Do something useful

37 of 75

Conditions (surprise review)

>>> if 2 < 3:

print("A")

elif 4 > 3:

print("B")

>>> if False:

print("hm")

elif "Python" > "JS":

print("not wrong")

>>> if False:

print("cold")

elif False:

print("flu")

elif True:

print("coronavirus")

Answers: A, not wrong, coronavirus

38 of 75

Loops - For

>>> for i in range(3):

print(i)

0

1

2

Take a variable and change its value each time we enter the loop.

39 of 75

Functions

def count_down():

print(“3…”)

time.sleep(1)

print(“2…”)

time.sleep(1)

print(“1…”)

time.sleep(1)

print(“I’ve literally frozen the entire game while my bot runs”)

count_down()

print(“And done!”)

40 of 75

Functions

def count_down():

for i in range(3):

print(i)

time.sleep(1)

This isn’t the exact same yet!

How can we clean up the count_down function using a for loop?

41 of 75

Functions - Arguments

def count_down(delay):

for i in range(delay):

print(i)

time.sleep(1)

Still not the same but it works.

How can we clean up the count_down function using a for loop?

Can we make the count_down more customizable?

How about count_down(3) or count_down(5)?

count_down(delay=5) is also valid!

42 of 75

Intermediate Python

Table of Contents�- Augmented assignment operators

- Casting

- Practice: Vertex formula

- return

- Lists, "append", "in"

- Dictionaries

- Multiple assignment

43 of 75

Augmented Assignment Operators

Replace, a = a + 3

With, a += 3

Similarly

*=, -=, /=, %=

44 of 75

Augmented Assignment Operators

Replace, a = a + 3

With, a += 3

Similarly

*=, -=, /=, %=

def get_negative(num):

result = 0

result -= num

print(result)

45 of 75

More Function Practice

Let’s make a function that gives the vertex of a quadratic.

f(x) = ax^2 + bx + c

The formula is x = -b / 2a.

get_vertex(1, 2, 3)

e.g. x^2 + 2x + 3

def get_vertex(a, b, c):

result = -b / (2 * a)

print(result)

46 of 75

More Casting Practice

What if we accidentally pass an str instead of a float?

get_vertex(“1”, “2”, “3”)

Crashes!

def get_vertex(a, b, c):

result = -float(b) / (2 * float(a))

print(result)

Looks messier but still works.

47 of 75

Returning to Functions

What if we want to store the result in a variable?

a = get_vertex(1, 2, 3)

Doesn’t crash but returns a special “None” value (like null).

def get_vertex(a, b, c):

result = -b / (2 * a)

return result

The function is evaluated and the returned variable becomes the value.

48 of 75

Returning to Functions

a = get_vertex(1, 2, 3)

What value is printed?

What does “a” become?

def get_vertex(a, b, c):

result = -b / (2 * a)

print(result)

return 1

49 of 75

Why return?

Helper functions

  • Write a small program to take an argument and give a result
  • Code re-use
  • First step into modules

50 of 75

Intro to lists

>>> stones = []

>>> stones.append("time")

>>> stones.append("space")

>>> stones.append("reality")

>>> stones

['time', 'space', 'reality']

>>> stones[0]

'time'

>>> stones[1]

'space'

>>> stones[2]

'reality'

51 of 75

Intro to lists

>>> stones

['time', 'space', 'reality']

>>> del stones[0]

>>> stones

['space', 'reality']

>>> stones[3]

Traceback (most recent call last):

IndexError: list index out of range

>>> stones[-1]

'reality'

>>> stones[-2]

'space'

52 of 75

Why lists?

  • Store a flexible amount of information in a single variable
    • Players in a game
    • Keeping track of items

>>> stones

['space', 'reality']

>>> "space" in stones

True

>>> "uw" in stones

False

53 of 75

Intro to Dictionaries

>>> classes = {}

>>> classes["ECON212"] = "PHYS"

>>> classes["PHYS124"] = "M3"

>>> classes

{'ECON212': 'PHYS', 'PHYS124': 'M3'}

>>> classes["ECON212"]

'PHYS'

>>> classes["PHYS467"]

Traceback (most recent call last):

classes["PHYS467"]

KeyError: 'PHYS467'

54 of 75

Intro to Dictionaries

>>> classes

{'ECON212': 'PHYS', 'PHYS124': 'M3'}

>>> del classes["ECON212"]

>>> classes

{'PHYS124': 'M3'}

>>> classes

{'PHYS124': 'M3'}

>>> "PHYS124" in classes

True

>>> "M3" in classes

False

55 of 75

Intro to Dictionaries

What kind of keys are possible?

Anything that’s hashable.

  • int, str, float

>>> classes

{'PHYS124': 'M3'}

>>> classes[314] = "pi"

>>> classes

{'PHYS124': 'M3', 314: 'pi'}

Can mix types of keys!

56 of 75

Multiple assignment

How do you swap two variables?

  • a, b = b, a

And that is all.

def bad_pi():

return 3, 1, 4

a, b, c = bad_pi()

print(a)

print(b)

print(c)

57 of 75

Guess the data structure

58 of 75

Guess the data type

country_status

Contains

"Alive":

"Filename":

"Health":

What data type is country_status?

"Alive":

"Filename":

"Health":

"ID": [A unique integer]

"Kills":

"Name":

"Nukes":

59 of 75

Intermediate Python 2

Table of Contents�- for loops revisited

- Nested data types

- Lists #2, "extend", "remove"

- break

- for else

- Sets

- Lists vs sets, performance

- Tuples

60 of 75

For loop

>>> stones

['space', 'reality', 'time']

>>> for i in stones:

print(i)

space

reality

time

The variable becomes each element in the list in sorted order.

>>> for i in range(3):

print(i)

0

1

2

61 of 75

Nested data types

>>> nested = []

>>> nested.append([])

>>> nested.append(not True)

>>> nested

[[], False]

>>> nested[0]

[]

>>> nested[0].append("hidden")

>>> nested[0]

['hidden']

>>> nested[0][0]

'hidden'

>>> nested

[['hidden'], False]

62 of 75

More List Operations

>>> nested = {}

>>> nested["one"] = ["a", "b"]

>>> nested["two"] = ["c", "d"]

>>> nested

{'one': ['a', 'b'], 'two': ['c', 'd']}

>>> nested["one"].extend(nested["two"])

>>> nested

{'one': ['a', 'b', 'c', 'd'], 'two': ['c', 'd']}

>>> nested["one"].remove("b")

>>> nested

{'one': ['a', 'c', 'd'], 'two': ['c', 'd']}

63 of 75

Break

>>> nested

{'one': ['a', 'c', 'd'], 'two': ['c', 'd']}

>>> for i in nested["one"]:

print(i)

a

c

d

>>> for i in nested["one"]:

if i == "c":

break

print(i)

a

64 of 75

Break

>>> while True:

count += 1

print(count)

1

2

3…

Program never ends.

>>> while True:

count += 1

print(count)

if count > 3:

break

1… 2…. 3… 4.

and then we stop.

65 of 75

While-else, for-else?

while [code]:

[code]

break

else:

[code]

Likely Python exclusive.

for [code]:

[code]

break

else:

[code]

66 of 75

Sets

Remember lists are ordered

>>> earth = ["a", "b"]

>>> L3 = ["b", "a"]

>>> earth == L3

False

>>> earth == ["a", "b"]

True

>>> rocket = ["r", "a", "c", "c", "o", "o", "n"]

>>> rocket

['r', 'a', 'c', 'c', 'o', 'o', 'n']

>>> set(rocket)

{'o', 'n', 'a', 'c', 'r'}

What happened?

67 of 75

Sets

Why sets?

  • Removing duplicates
    • list(set(x))
  • Faster!
    • in happens in constant rather than linear time compared to list
      • List “in” searches the entire list
      • Set “in” uses hashing

>>> mush = set(rocket)

>>> mush

{'o', 'n', 'a', 'c', 'r'}

>>> mush.remove("o")

>>> mush.add("hmm")

>>> mush

{'n', 'a', 'c', 'hmm', 'r'}

68 of 75

Tuples

>>> earth = ["rocks", "ice"]

>>> mars = tuple(earth)

>>> mars

('rocks', 'ice')

Tuples use ( ) instead of [ ].

>>> mars.append("people")

Traceback (most recent call last):

mars.append("people")

AttributeError: 'tuple' object has no attribute 'append'

People don’t go to Mars. Tuples are immutable.

69 of 75

Tuples

Why tuples?

  • Immutable
    • Safer
    • Faster
      • Not as fast as sets
  • Stores duplicates and order

>>> mars + mars

('rocks', 'ice', 'rocks', 'ice')

>>> earth + earth

['rocks', 'ice', 'rocks', 'ice']

Why does this work?

We can still build new tuples (and lists) from old ones.

70 of 75

Back to the Game

71 of 75

Running the Game

  • Game.py
    • The text version of the game which you can run to watch bots compete
  • Graphical.py
    • The graphical version which needs Pygame (strongly recommended)
      • Difficult to set up
  • Batch.py
    • Runs thousands of games and shows the winner
    • Uses multiple cores!

72 of 75

API

  • We use dictionaries containing keys to various data types

  • country_status describes the statistics of your own country (health, your ID, your number of nukes)
  • world_state describes everything else
    • Information on each country, all previous events (such as weapons fired), and a set of living players

73 of 75

Bots Directory

  • Each Python file here contains a single class representing a bot
    • More on OOP next week!

  • API.txt contains information on the API
    • Will be finalized by Lesson 2

74 of 75

Sample Bot

  • Here we see an example of a library being used in Python
    • random.choice is used to pick a random element from an array
    • random.randint is used to pick a random integer (weapons are integers)

  • country_status and world_state are arguments that describe the situation
  • We return a dictionary with two arguments to represent our action

75 of 75

Next Time

  • Learn about object-oriented programming
  • Build a bot together in class
  • Make sure you install Python and Pygame for next week
    • Ask for help on Slack since the start is the hardest part
    • Make sure you can open py files with IDLE (or an IDE of your choice)

Good luck with interviews / midterms. Ask me anything.