{
"metadata": {
"name": "",
- "signature": "sha256:5e9f030b42097ebbcce2654cdb1d9370fde38b61bdbfa85a0cc700e76d5a8a71"
+ "signature": "sha256:8dfb2bb1cf596c711c837f4c7c2d8706f9dcacc1a0ffc3dc21c1d0fedd3fc6bf"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#Putting both halves together\n",
+ "We now have systems that can do both halves of the Hangman game. Now it's time to put them together so that we can get a machine to play itself. At the moment, let's concentrate on just the plumbing: let's get the two halves working together. In the next step, we'll think about different strategies and compare their effectiveness.\n",
+ "\n",
+ "The word of this section is \"encapsulation.\" \n",
+ "\n",
+ "First, a change in terminology. We'll call a `player` the thing that makes the guesses (the guesser player from before). We'll call a `game` the thing that handles receiving guesses, updating `discovered` words, updating lives and all of that. That's what was the setting player from before, but without the bit about picking a random word. We'll have the `game` accept the `target` as a parameter, so that we can test everything more easily (if we know what word the `player` is trying to guess, we can predict what it should do).\n",
+ "\n",
+ "Back to encapsulation.\n",
+ "\n",
+ "We want to bundle all the state information for a `game` into one 'thing' so that we don't need to worry about global variables. We will also want to bundle up everything to do with a `player` into one 'thing' so we can tell the game about it. For the `player`, the thing will include both any state it needs and the definition of that `player`'s guessing strategy. We're also going to have a bunch of related players, all doing much the same thing but with different strategies.\n",
+ "\n",
+ "In this case, objects seem like a natural fit.\n",
+ "\n",
+ "(Insert Neil's aikido instructor story here.)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##Object-orientation in Python\n",
+ "There are a few things to remember about object orientation in Python.\n",
+ "\n",
+ "1. It's an ugly kludge that was bolted on long after the language was defined.\n",
+ "\n",
+ "2. `self` needs to be passed in to all object methods as the first parameter, though it doesn't appear when you call the method.\n",
+ "\n",
+ "3. Use `self.whatever` to refer to the instance variable `whatever`\n",
+ "\n",
+ "4. Use `self.however(arg1, arg2)` when one method calls another in the same object.\n",
+ "\n",
+ "Apart from that, it's pretty straightforward."
+ ]
+ },
{
"cell_type": "code",
"collapsed": false,
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 71
+ "prompt_number": 43
},
{
"cell_type": "code",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 72
+ "prompt_number": 44
},
{
"cell_type": "code",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 73
+ "prompt_number": 45
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This is pretty much the same code as for the `setter` part, just with plenty of `self` statements scatter around. A few things to note:\n",
+ "\n",
+ "* `initialise()` is now named `__init__()` (note the double underscores fore and aft).\n",
+ "* `player` and `lives` are parameters to the `game`, but with default values.\n",
+ "* I've added two new flags, `game_won` and `game_lost`.\n",
+ "* `do_turn` asks the player for a guess, if there is a player.\n",
+ "* The `guess()` method of the `player` is passed the `lives`, in case the guess should change depending on the progress of the game (the `player` can always ignore it).\n",
+ "* After a guess has been processed, `do_turn` has a few more statements to set the relevant flags to represent the state of the game.\n",
+ "* `report_on_game()` has been added for when the game is being played against a human."
+ ]
},
{
"cell_type": "code",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 74
+ "prompt_number": 46
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's test it!"
+ ]
},
{
"cell_type": "code",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 75
+ "prompt_number": 47
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 76,
+ "prompt_number": 48,
"text": [
- "'strife'"
+ "'distension'"
]
}
],
- "prompt_number": 76
+ "prompt_number": 48
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 77,
+ "prompt_number": 49,
"text": [
- "['_', '_', '_', '_', '_', '_']"
+ "['_', '_', '_', '_', '_', '_', '_', '_', '_', '_']"
]
}
],
- "prompt_number": 77
+ "prompt_number": 49
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n"
+ "Word: _ _ _ _ _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n"
]
},
{
]
}
],
- "prompt_number": 78
+ "prompt_number": 50
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 79,
+ "prompt_number": 51,
"text": [
"10"
]
}
],
- "prompt_number": 79
+ "prompt_number": 51
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 80,
+ "prompt_number": 52,
"text": [
"[]"
]
}
],
- "prompt_number": 80
+ "prompt_number": 52
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ _ e : Lives = 10 , wrong guesses: \n"
+ "Word: _ _ _ _ e _ _ _ _ _ : Lives = 10 , wrong guesses: \n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: d\n"
+ "Enter letter: q\n"
]
}
],
- "prompt_number": 81
+ "prompt_number": 53
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 82,
+ "prompt_number": 54,
"text": [
"9"
]
}
],
- "prompt_number": 82
+ "prompt_number": 54
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 83,
+ "prompt_number": 55,
"text": [
- "['_', '_', '_', '_', '_', 'e']"
+ "['_', '_', '_', '_', 'e', '_', '_', '_', '_', '_']"
]
}
],
- "prompt_number": 83
+ "prompt_number": 55
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 84,
+ "prompt_number": 56,
"text": [
- "['d']"
+ "['q']"
]
}
],
- "prompt_number": 84
+ "prompt_number": 56
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n"
+ "Word: _ _ _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: d\n"
+ "Enter letter: e\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ _ _ d : Lives = 10 , wrong guesses: \n"
+ "Word: e _ e _ _ _ _ e : Lives = 10 , wrong guesses: \n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: e\n"
+ "Enter letter: x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 10 , wrong guesses: \n"
+ "Word: e _ e _ _ _ _ e : Lives = 9 , wrong guesses: x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: f\n"
+ "Enter letter: s\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 9 , wrong guesses: f\n"
+ "Word: e _ e _ _ _ _ e : Lives = 8 , wrong guesses: s x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: e\n"
+ "Enter letter: l\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 9 , wrong guesses: f\n"
+ "Word: e _ e _ _ _ _ e : Lives = 7 , wrong guesses: l s x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: s\n"
+ "Enter letter: t\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 8 , wrong guesses: f s\n"
+ "Word: e _ e _ _ _ _ e : Lives = 6 , wrong guesses: l s t x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: t\n"
+ "Enter letter: m\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 7 , wrong guesses: f s t\n"
+ "Word: e _ e _ _ _ _ e : Lives = 5 , wrong guesses: l m s t x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: n\n"
+ "Enter letter: h\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 6 , wrong guesses: f n s t\n"
+ "Word: e _ e _ _ _ _ e : Lives = 4 , wrong guesses: h l m s t x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: m\n"
+ "Enter letter: i\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 5 , wrong guesses: f m n s t\n"
+ "Word: e _ e _ _ _ _ e : Lives = 3 , wrong guesses: h i l m s t x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: h\n"
+ "Enter letter: a\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 4 , wrong guesses: f h m n s t\n"
+ "Word: e _ e _ _ _ _ e : Lives = 2 , wrong guesses: a h i l m s t x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ _ _ e d : Lives = 3 , wrong guesses: f h m n o s t\n"
+ "Word: e _ e _ _ o _ e : Lives = 2 , wrong guesses: a h i l m s t x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: i\n"
+ "Enter letter: n\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ e _ i _ e d : Lives = 3 , wrong guesses: f h m n o s t\n"
+ "Word: e _ e _ _ o n e : Lives = 2 , wrong guesses: a h i l m s t x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: r e _ i r e d : Lives = 3 , wrong guesses: f h m n o s t\n"
+ "Word: e _ e r _ o n e : Lives = 2 , wrong guesses: a h i l m s t x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: w\n"
+ "Enter letter: v\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "Word: e v e r _ o n e : Lives = 2 , wrong guesses: a h i l m s t x\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "Enter letter: y\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "You won! The word was rewired\n"
+ "You won! The word was everyone\n"
]
},
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 85,
+ "prompt_number": 57,
"text": [
"True"
]
}
],
- "prompt_number": 85
+ "prompt_number": 57
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ _ : Lives = 10 , wrong guesses: \n"
+ "Word: _ _ _ _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: e\n"
+ "Enter letter: q\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ _ : Lives = 9 , wrong guesses: e\n"
+ "Word: _ _ _ _ _ _ _ _ _ : Lives = 9 , wrong guesses: q\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: s\n"
+ "Enter letter: z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ s : Lives = 9 , wrong guesses: e\n"
+ "Word: _ _ _ _ _ _ _ _ _ : Lives = 8 , wrong guesses: q z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: t\n"
+ "Enter letter: x\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ s : Lives = 8 , wrong guesses: e t\n"
+ "Word: _ _ _ _ _ _ _ _ _ : Lives = 7 , wrong guesses: q x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: o\n"
+ "Enter letter: e\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ s : Lives = 7 , wrong guesses: e o t\n"
+ "Word: _ _ _ _ _ _ _ _ _ : Lives = 6 , wrong guesses: e q x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: i\n"
+ "Enter letter: a\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ s : Lives = 6 , wrong guesses: e i o t\n"
+ "Word: _ _ a _ _ _ _ _ _ : Lives = 6 , wrong guesses: e q x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: u\n"
+ "Enter letter: v\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ s : Lives = 5 , wrong guesses: e i o t u\n"
+ "Word: _ _ a _ _ _ _ _ _ : Lives = 5 , wrong guesses: e q v x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: a\n"
+ "Enter letter: b\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ _ _ _ s : Lives = 4 , wrong guesses: a e i o t u\n"
+ "Word: _ _ a _ _ _ _ _ _ : Lives = 4 , wrong guesses: b e q v x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: y\n"
+ "Enter letter: k\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ y _ _ s : Lives = 4 , wrong guesses: a e i o t u\n"
+ "Word: _ _ a _ k _ k _ _ : Lives = 4 , wrong guesses: b e q v x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: w\n"
+ "Enter letter: l\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: _ y _ _ s : Lives = 3 , wrong guesses: a e i o t u w\n"
+ "Word: _ _ a _ k _ k _ _ : Lives = 3 , wrong guesses: b e l q v x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: h\n"
+ "Enter letter: j\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: h y _ _ s : Lives = 3 , wrong guesses: a e i o t u w\n"
+ "Word: _ _ a _ k _ k _ _ : Lives = 2 , wrong guesses: b e j l q v x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: m\n"
+ "Enter letter: p\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Word: h y m _ s : Lives = 3 , wrong guesses: a e i o t u w\n"
+ "Word: _ _ a _ k _ k _ _ : Lives = 1 , wrong guesses: b e j l p q v x z\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "Enter letter: n\n"
+ "Enter letter: d\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
- "You won! The word was hymns\n"
+ "You lost. The word was sharkskin\n"
]
},
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 86,
+ "prompt_number": 58,
"text": [
- "True"
+ "False"
]
}
],
- "prompt_number": 86
+ "prompt_number": 58
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 108,
+ "prompt_number": 59,
"text": [
- "'six'"
+ "'sharkskin'"
]
}
],
- "prompt_number": 108
+ "prompt_number": 59
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Player objects\n",
+ "Let's work ourselves gently into this.\n",
+ "\n",
+ "In the first instance, the only thing a `player` needs is to respond to the `guess` method. Let's make objects with just this method. Let's even make it simpler than the player from the `guesser` stage, and have it just guess letters in alphabetical order."
+ ]
},
{
"cell_type": "code",
"input": [
"class PlayerAlphabetical:\n",
" def guess(self, discovered, missed, lives):\n",
- " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
- " return [l for l in string.ascii_lowercase if l not in guessed_letters][0]"
+ " return [l for l in string.ascii_lowercase if l not in discovered + missed][0]"
],
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 109
+ "prompt_number": 60
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "That wasn't too hard, was it?\n",
+ "\n",
+ "Let's use it to play a game."
+ ]
},
{
"cell_type": "code",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 110
+ "prompt_number": 69
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 111,
+ "prompt_number": 70,
"text": [
"False"
]
}
],
- "prompt_number": 111
+ "prompt_number": 70
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 112,
+ "prompt_number": 71,
"text": [
- "['l', 'e', 'g', 'a', 'l', 'l', '_']"
+ "['c', 'e', '_', '_', 'i', 'f', 'i', 'c', 'a', '_', 'e', '_']"
]
}
],
- "prompt_number": 112
+ "prompt_number": 71
},
{
"cell_type": "code",
{
"metadata": {},
"output_type": "pyout",
- "prompt_number": 113,
+ "prompt_number": 72,
"text": [
- "'legally'"
+ "'certificates'"
]
}
],
- "prompt_number": 113
+ "prompt_number": 72
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Bored with looking at all the state of the game with different cells. Let's have a `print()` statement that tells us what we need."
+ ]
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: cavalry ; Discovered: ['c', 'a', '_', 'a', 'l', '_', '_'] ; Lives remaining: 0\n"
+ "Target: turnoffs ; Discovered: ['_', '_', '_', '_', '_', 'f', 'f', '_'] ; Lives remaining: 0\n"
]
}
],
- "prompt_number": 114
+ "prompt_number": 74
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Another player\n",
+ "Let's reimplement our player that does letters in frequency order. Again, this is essentially code reused from earlier."
+ ]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
- "LETTER_COUNTS = collections.Counter(l.lower() for l in open('sherlock-holmes.txt').read() if l in string.ascii_letters)\n",
+ "LETTER_COUNTS = collections.Counter(l.lower() for l in open('../sherlock-holmes.txt').read() if l in string.ascii_letters)\n",
"LETTERS_IN_ORDER = [p[0] for p in LETTER_COUNTS.most_common()]\n",
"\n",
"class PlayerFreqOrdered:\n",
" def guess(self, discovered, missed, lives):\n",
- " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
- " return [l for l in LETTERS_IN_ORDER if l not in guessed_letters][0]"
+ " return [l for l in LETTERS_IN_ORDER if l not in discovered + missed][0]"
],
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 115
+ "prompt_number": 76
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: deathblow ; Discovered: ['d', 'e', 'a', 't', 'h', '_', 'l', 'o', 'w'] ; Lives remaining: 0\n"
+ "Target: cartons ; Discovered: ['c', 'a', 'r', 't', 'o', 'n', 's'] ; Lives remaining: 2\n"
]
}
],
- "prompt_number": 116
+ "prompt_number": 77
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: littered ; Discovered: ['l', 'i', 't', 't', 'e', 'r', 'e', 'd'] ; Lives remaining: 5\n"
+ "Target: douching ; Discovered: ['d', 'o', 'u', 'c', 'h', 'i', 'n', '_'] ; Lives remaining: 0\n"
]
}
],
- "prompt_number": 117
+ "prompt_number": 78
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: licenced ; Discovered: ['l', 'i', 'c', 'e', 'n', 'c', 'e', 'd'] ; Lives remaining: 1\n"
+ "Target: minimisation ; Discovered: ['m', 'i', 'n', 'i', 'm', 'i', 's', 'a', 't', 'i', 'o', 'n'] ; Lives remaining: 4\n"
]
}
],
- "prompt_number": 118
+ "prompt_number": 79
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Player subclasses and inheritance\n",
+ "Time to DRY the code a little. Both of these players (`PlayerAlphabetical` and `PlayerFreqOrdered`) are essentially the same. The only difference is the set of letters used in the middle of the `guess` method. \n",
+ "\n",
+ "Let's create a generic \"letters in a fixed order\" class that has that implementation of `guess` and is passed in a set of letters in order. The two players we already have are subclasses of that, where we have pre-packaged letter orders.\n",
+ "\n",
+ "Here's the generic player. Note that the ordered letters are passed in as a parameter to the `__init__()` method, and `guess()` uses that letter sequence."
+ ]
},
{
"cell_type": "code",
" self.ordered_letters = ordered_letters\n",
" \n",
" def guess(self, discovered, missed, lives):\n",
- " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
- " return [l for l in self.ordered_letters if l not in guessed_letters][0]"
+ " return [l for l in self.ordered_letters if l not in discovered + missed][0]"
],
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 119
+ "prompt_number": 85
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can now specify the subclasses, using the fixed order. The initialisation of the subclasses now takes no additional parameter, but we pass the hardcoded order to the superclass's `__init__()`."
+ ]
},
{
"cell_type": "code",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 120
+ "prompt_number": 86
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Does it work?"
+ ]
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: unworthier ; Discovered: ['u', 'n', 'w', 'o', 'r', 't', 'h', 'i', 'e', 'r'] ; Lives remaining: 5\n"
+ "Target: yogi ; Discovered: ['_', 'o', '_', 'i'] ; Lives remaining: 0\n"
]
}
],
- "prompt_number": 121
+ "prompt_number": 87
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: kneel ; Discovered: ['_', 'n', 'e', 'e', 'l'] ; Lives remaining: 0\n"
+ "Target: slimmest ; Discovered: ['s', 'l', 'i', 'm', 'm', 'e', 's', 't'] ; Lives remaining: 3\n"
]
}
],
- "prompt_number": 122
+ "prompt_number": 88
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: provisoes ; Discovered: ['_', '_', '_', '_', 'i', '_', '_', 'e', '_'] ; Lives remaining: 0\n"
+ "Target: diseases ; Discovered: ['d', 'i', '_', 'e', 'a', '_', 'e', '_'] ; Lives remaining: 0\n"
]
}
],
- "prompt_number": 123
+ "prompt_number": 89
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Can we use the generic version directly?"
+ ]
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: invincible ; Discovered: ['_', '_', 'v', '_', '_', '_', '_', '_', '_', '_'] ; Lives remaining: 0\n"
+ "Target: pardon ; Discovered: ['p', '_', 'r', '_', 'o', 'n'] ; Lives remaining: 0\n"
]
}
],
- "prompt_number": 124
+ "prompt_number": 90
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "Target: clogging ; Discovered: ['_', '_', '_', '_', '_', '_', '_', '_'] ; Lives remaining: 0\n"
+ "Target: grouchier ; Discovered: ['_', 'r', 'o', 'u', '_', '_', '_', '_', 'r'] ; Lives remaining: 0\n"
]
}
],
- "prompt_number": 125
+ "prompt_number": 91
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##Mass gaming\n",
+ "Now we can get machines playing each other, we get get them playing *lots* of games and just tell us the summaries. \n",
+ "\n",
+ "Which of these three methods (alphabetical, frequency ordered, reverse alphabetical) is the best? Let's get each player to play 100 random games and see which gets the most wins."
+ ]
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "44\n"
+ "49\n"
]
}
],
- "prompt_number": 126
+ "prompt_number": 92
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "320\n"
+ "309\n"
]
}
],
- "prompt_number": 127
+ "prompt_number": 96
},
{
"cell_type": "code",
"output_type": "stream",
"stream": "stdout",
"text": [
- "7\n"
+ "6\n"
]
}
],
- "prompt_number": 128
+ "prompt_number": 94
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Frequency ordered is much better than the others, but still only wins about 30% of the time. I'm sure we can do better.\n",
+ "\n",
+ "That's the next part..."
+ ]
},
{
"cell_type": "code",
"input": [],
"language": "python",
"metadata": {},
- "outputs": [],
- "prompt_number": 128
+ "outputs": []
}
],
"metadata": {}