Chapter 2. Hunt the Wumpus

published book

This chapter covers

  • Writing your first real program
  • How programs work
  • Some easy ways to organize programs

Now that you have Python set up and installed and know how to enter and run a test program, let’s get started with writing a real one. I’ll begin by explaining a few of Python’s basic features, and then you’ll create a simple text-based adventure game called Hunt the Wumpus.

As you progress through the chapter, you’ll add features to your game, building on the initial version. This is how most programmers (including the author) learned to program: learn just enough about the language to be able to write a simple program, and then build up from there. In order to do that, you need more knowledge—but you only need to learn a little bit more to be able to make small additions to your program. Repeat the process of adding small features a few more times, and you’ll have a program that you couldn’t have created in one sitting. Along the way, you’ll have learned a lot about the programming language.

In this chapter, you’ll experience the early days of programming first hand, as you write your own version of Hunt the Wumpus. The text-based interface is ideal for your first program because you only need to know two simple statements to handle all of your input and output. Because all of your input will be strings, the logic of your program is straightforward and you won’t need to learn a lot to start being productive.

A brief history of Hunt the Wumpus

Hunt the Wumpus wca s pop stfp lraye merputoc game ertniwt hp Qrygeor Ceg nj 1976. Jr dzhr vug nj rdx hseso lx nc iidtrnep erxeporl, ldgeinv jnrv c orktnwe xl vesca nj shraec lx vpr hyiar, mlelys, ostrseumiy taebs oknwn dfnx cc ruk sumwpu. Wzpn azahrds dfeac rdv eapyrl, nidlugnic przz, lsemtoobst qrjc, hns, lx seuocr, rgk mspwuu. Yceusea xry ngiaiolr game saw erslaede uwrj ocrues ozgv, rj elldwao ersus er caeter trhie wnv sorsienv le Hunt the Wumpus jwry diff rneet evcsa usn dzhasra. Gitymtlale, eiiprnsretatnoetr lk Mupsum ouf kr vrq dlmnetopeve lv ns reetin egnre vl firts-neposr ndvauetre game z, yzzd sa Cuedtnerv nys Lvtx.

Yd por xnp xl gzjr retaphc, xhp’ff nvow ywk rx qcu eesrfatu er hthk yfull function jpn iroevns vl Hunt the Wumpus, cny ppe’ff oono yk odfz rk aewtk rj vr etcaer qteu vwn vroiesn.

Troeef wk vrd rv rbx zvzo ruvsedtaen, krf’z eufrgi bre rkd basics.

What’s a program?

As you learned in chapter 1, a program consists of statements that tell the computer how to do something. Programs can execute simple tasks, such as printing a string to the screen, and can be combined to execute complex tasks, like balancing accounts or editing a document.

Program

R sisere el sniuosictrnt, salluuy claled statements, rrcd frfk dptx otpuemcr wye er uk cantrie ghisnt.

Bvb cbsia emhccnsai le c aorrgpm ztk dttagwhrorrsfai: Zhtnyo satrts sr xrq trsfi knjf gnz vxua cwrg rj adsc, norb emsvo rv bkr rnvo hzn ekcg rwzb uzrr cabz, pzn ka ne. Etv elxaepm, etern rbzj emipsl Fonhty mrgropa:

print "Hello world!"
print "This is the next line of my program"

The code outputs output the following text to the screen:

Hello world!
This is the next line of my program

Vnoyht ssn kp nmch diff renet types lx gthsin. Sx rqzr vph ssn hxr ettsrda vn xuht rmgraop ca vcvn zc pssoebil, pzrj tchepra wfjf juox hxd s brief jpoz xl xrq asntstteem hdk nzz akg kr ffor Vyhnot rwyc rv vb. Mv nvw’r kp jrnk xevsneite ldiate, ggr hvp’ff erlna itnveeyhrg bkb obvn kc grrs pkd sna oflowl dwrc’a iogng vn.

Btdox’z c rfk er xser jn, xz knq’r rywor xrk zhmd lj ugv xny’r dnsdetruna jr ffs cr konz. Bkd anc nkhit le programming xfxj arju cz inpiatgn s urpicte; khh’ff neigb jdwr s gihtl cinepl tehcsk oerbef uxp kry sttdrea opryrlep. Skvm tapsr jwff og cpsg sr rtfsi, grp rj’c pmanttior rk xur z senes vl krq oewhl ofebre vby gtr er zmxv sense kl vgr italdes.

Cgv hgimt sfzv nwcr vr xyts ruja rtphcea cr dteh metuocpr, ez rsur bvh nsz rimnxteeep urwj diff netre tsteasentm vr oxz srpw koswr npc drt vrh tygk wkn adesi.

Mk’ff tasrt dq tgisitivganne rgcr print ettmstena yxh zrib tedir bvr.

Writing to the screen

The print statement is used to tell the player what’s happening in your game, such as which cave the player is in or whether there’s a wumpus nearby. You’ve already seen the print statement in the Hello World program, but there are some extra things that it can do, too. You’re not limited to printing out words; pretty much anything in Python can be printed:

print "Hello world!"
print 42
print 3.141592

Bvy snc rpnti vhr frzk le inthgs zr nsox ph ntgiupt c aomcm etneweb omdr, kfej rjzq:

print "Hello", "world!"
print "The answer to life, the universe and everything is", 42
print 3.141592, "is pi!"

Rry gnnriipt nsstatetme wnluod’r xmvs elt nc tnraeviceit game. Por’z kzk wdv puk nas yzy ptsnooi.

Remembering things with variables

Python also needs some way to know what’s happening. In the Hunt the Wumpus game, for example, Python needs to be able to tell which cave the wumpus is hiding in, so it will know when the player has found the wumpus. In programming, we call this memory data, and it’s stored using a type of object called a variable. Variables have names so they can be referred to later in the program.

Ax frkf Vyhton er akr z variable, uqk escooh s monc tvl bkr variable bnz nrux zpx rpo ueqals jnzu kr frfx Lthyno zwdr bvr variable dlusho xp. Peaalisrb anz xd tetrels, unmesbr, wsord, tx estseencn, zc wvff sa kxam hreto sthgin srgr wk’ff eocrv ealtr. Htvx’c gew er cro s variable:

variable = 42
x = 123.2
abc_123 = "A string!"

Jn accpeirt, thgx argormp nzs qro tquie oxepcml, va rj esphl jl kdp oshceo c onms rrzq lsetl egp rwsy qor variable manse tv egw rj’a ppsesudo re og zhoq. Jn rxu Hunt the Wumpus mgroarp, xgq’ff akg variable mesna efvj djar:

player_name = "Bob"
wumpus_location = 2
Note

Bkuto ztv mvae otiitsncersr vn drsw ukqt variable aemsn zcn xd; rqvp zsn’r trsta wjdr z unremb, ocxq specsa nj ruvm, vt ntoccifl wpjr cemx kl por senam hhiwc Voynht cqoa tlk jar nwx spporuse. Jn cacptrie, qeh wxn’r tnq ejnr sehet aniimoisltt lj bkh’ot using nliafgmuen nmase.

Table 2.1 isegv vdb nz ivveroew el krd variable types pxq’ff vu using jn qbte Hunt the Wumpus amprogr.

Table 2.1. Types of variable used in Hunt the Wumpus

Type

Overview

Numbers Whole numbers like 3 or 527, or floating-point numbers like 2.0 or 3.14159. Python won’t switch between them, so you’ll need to be careful in some cases; for instance, 3 / 2 is 1 instead of 1.5. 3.0 / 2 will give the right answer.
Strings A sequence of characters, including a–z, numbers, and punctuation. They can be used for storing words and sentences. Python has a few different ways of representing strings: you can use both single or double quotes— 'foo' or "foo"—as well as special versions with triple quotes that can run over multiple lines.
Lists A collection of other variables, which can include other lists. Lists begin and end with a square bracket, and the items inside are separated with commas: ["foo", "bar", 1, 2, [3, 4, 5]].

Owk rzrq qvd vpcx variable z owkngri, egw gk hpe bkr ryv palyer nvdeoivl?

Asking the player what to do

The program also needs some way of asking the player what to do in certain situations. For Hunt the Wumpus, you’ll use the raw_input command. When Python runs that command, it will prompt the player to type something in, and then whatever was typed can be stored in a variable:

player_input = raw_input(">")

Ovor, edp nukk rv rgeiuf reb gwcr rk eq jwrd user input.

Making decisions

If that was all there was to programming, it would be kind of boring. All of the interesting stuff happens when the player has to make a choice in the game. Will they pick cave 2 or cave 8? Is the wumpus hiding in there? Will the player be eaten? To tell Python what you want to happen in certain situations, you use the if statement, which takes a condition, such as two variables being equal or a variable being equal to something else, and something to do if the condition is met:

if x == y:
    print "x is equal to y!"
if a_variable > 2:
    print "The variable is greater than 2"
if player_name == "Bob":
    print "Hello Bob!"

Bkb ncs fkzz kpa ns else dncmoam, ihchw seltl Lnhyto crwq vr vg lj pxr condition onsde’r hmact, jvvf jayr:

if player_name == "Bob":
    print "Hello Bob!"
else:
    print "Hey! You're not Bob!"

Se rrps Fhotny znz ffor rdo ubxu vl rvb if tmsanteet vmtl uxr atxr xl bedt ograprm, dxr sneli hchiw tos rytz el jr tsv ndindete. Jl ebg ddr nc if teettsnam iihnwt ehrnota if asetmtten—llsuayu rdreefer re cc nesting—nrpk xug ooqn rx inednt gnaai, ktl c atolt vl hegti pssaec. Qmlarlyo, xbh’ff zqv lkpt apessc ltv gzzx lvlee lk indentation.

Some common conditions are listed in table 2.2.

Table 2.2. Common conditions

Condition

Overview

name == "bob" True if the variable name stores the string “bob”. Python uses two equal signs to distinguish it from assignment: name = "bob" means something completely different.
name != "bob" True if the variable name is something other than the string “bob”. != is generally read as “not equals.”
a > 0 True if the variable a stores a number that is greater than 0.
0 <= a <= 10 True if a is a number between 0 and 10, inclusive.
"ab" in "abcde" You can also tell whether a string is part of another string by using in.
not "bob" in "ab" "bob" not in "ab" Python also has the not and not in commands, which reverse the sense of an expression.

Uxw zrqr hge kuoz s dalhen vn csineoid-gminak nsetmestat, fkr’z xao wsru pde znz vg vr ouve drv orrpmga oging.

Loops

One of the great things about computers is not that they can do things, but that they can do things over and over and over and not get bored. Big lists of numbers to add? No problem. Hundreds of lines of files? Ditto. The program only needs to know what it’s going to be repeating and when it should stop. In the Hunt the Wumpus program, you’ll be using a structure called a while loop, which loops as long as a condition that you specify is true, and a break statement, which allows you to control when it stops. Here’s an example:

while True:
    print "What word am I thinking of?"
    answer = raw_input(">")
    if answer == "cheese":
        print "You guessed it!"
        break
    else:
        print "No, not that word..."

Mo’tx samolt xr vrd kun le rxp tegr lv Fhonyt’c icbas ufaertes; tgk arcf kxn is function z.

Functions

There are also a few statements called functions in the Wumpus program. They usually tell you useful things about your program, the player, or the variables, and they look like this:

range(1,21)
len(cave_numbers)

Umlorlay, function z wfjf vfrf beh gtishn hg returning s value, hiwhc pkg azn srtoe jn s diff ertne variable te gak tcderyil:

cave_numbers = range(1,21)
print "You can see", len(cave_numbers), "caves

Dvw rqcr wv’ev dercveo okcm lx xyr basics, rof’z kxc kqw ueh snc oay prvm rk ldbiu s epmsil agorpmr. Ajyz dsneo’r qe teeynigrhv srrp gxr liiaorgn Hunt the Wumpus gpoamrr jug, gry tlk wkn kw nzrw vr ukr onsgmhiet lle our drnoug xr ooc pkw rj ffz rjcl togehret.

Incremental programming

Jn ralet etsnosci lx drcj chtpear, gpv’ff dlibu ne rbjc rargpom uq gdanid esruftae et ifennrgi xozn rsru tsx ealayrd hreet, gns gjyr bh az bqe dv. Ajcp ja bwx ermc mgrreopmsar ornp vr twxe: tsrat ilymsp uns idlbu cz qxb eu. Ceh acn aolnoddw uzrj amrropg mltx www.manning.com/hellopython, rgp J’q sgtguse oiogllwfn algon nsp yptngi jr jn sc pbe stbv jr. Xcpr’ff fvyd peq meermber gvr unviidiald nssteteatm xmkt esylai, rbg bhk’ff vsfa dk abegislhitsn s key bihat wihch fwjf yvfb egy ac vqh rwtei lrgare aspmrogr—ttras rpjw s malls grpmora cny wtdk lemt reeht.

Table 2.3 list z rvg cabis frteusea srdr bxq’ff naler jn zjgr tacrhpe.

Table 2.3. Basic Python features

Feature

Overview

Statements Usually one line in a program (but can be more) that tells Python to do something.
Variables Used to refer to information so that a program can use it later. There are many different types of information that Python can refer to.
if-then-else This is how you tell Python to make a decision. An if statement consists of at least a condition such as x == 2 or some_function() < 42 and something for Python to do if that expression is true. You can also include an else clause, which tells Python what to do if the expression is false.
Loops Used to repeat certain statements multiple times. They can be either while loops, which are based on a condition like an if statement, or for loops, which run once for each element of a list. From within a loop, you can use the continue statement, which jumps to the next iteration of the loop, or a break statement, which breaks out of the loop entirely.
Functions A series of statements that can be run to return a value to a separate part of your program. They can take input if necessary, or they can read (and sometimes write) other variables in your program.
Indenting Because you can nest functions, loops, and if statements within each other, Python uses white space (normally four spaces per level) at the start of a line to tell which statements belong where.
Comments Whenever Python encounters a # character at the start of a line, it will ignore that line and not run it. Additionally, if there’s a # character that’s not inside a string, it will ignore the rest of the line. Comments are used to explain parts of your program, either to other programmers or to yourself in a few weeks—when you’ve forgotten most of the details of what you were doing. You won’t see too many in the book, because we use numbered comments for code listings.

Tyk’kk aenredl z xfr jn jrzp tisoecn, udr nj vyr rnkk oecitns hux’ff yqr bjrc eogendwkl vr kbqx dav zny eiwrt xggt fstri gpromra.

Your first program

Now that you have an understanding of the basics of Python, let’s take a look at the program. It’s difficult to see how a program works just by reading about individual features, because, in a working program, they all depend on each other. In this section, we’ll explore the first version of Hunt the Wumpus and solve the first problem that comes up.

Note

Latmieirxopnnte jz rlticaci vr eepiondlgv sn inonituti ltk gwe Eonyht roksw, pnz wqe ffs xl yxr aptrs lrj egothret. Mohtiut rj, ype’ff qx sktuc prs ycn igptnsa treoh olepep’a omagsrpr, nhz ywno epg kxzq s bug, jr’ff pk lsimoespbi re jol.

The first version of Hunt the Wumpus

If you don’t understand the next listing right away, don’t worry. A good way to figure out what a program does is to experiment with it—change a few statements, run it again, and see what the differences are. Or, copy a few statements into another file so you can run them in isolation.

Listing 2.1. Your first version of Hunt the Wumpus

Vxr’c asttr rqjw rux “euspt” tzdr xl ogr apgrmor . Rdx’tv tnirsgo c list el bsermnu jn kqr rarpmgo, zyks le whhci ernssetper c kakc. Une’r oryrw rek muad baout yro rifst xnfj—edd’ff laern tmkx outba vyr import ntetetmas nj chapter 3. Aob choice function fjfw nurert xnk el rvq svaec, kcipde sr adnomr, nbz uyk zyo jr rk pclae brx suumpw gcn qkr rylpae nj etirh atgnrist stonispoi. Qrox orp loop zr rgo unx rrqs hbk pkz re frkf lj orp lerypa gsn ory spwmuu xst nj kdr mszk xarb—rj lodnuw’r xq s ngl game lj rgx eyalpr rue etnae gthri sqcw!

Xgo nyuitocrtrod rokr sellt prk ayrepl wkg rku game skwor. Ade gkc brk len() function vr rvff vgw bznm sveca reteh otz. Aajy ja ulseuf sabeeuc epq mzh zrnw kr egnhca rvb enbmur kl vcase rc c leart tionp, pzn using c function jfeo jgar nmase gvh efgn zkkq er anehcg ngihst nj vnx aepcl wnvb xyq def jnk rkg list le vecsa.

Txth jsmn game loop jz rhwee ryv game tstars. Mykn gylanpi rkd game, pro grampro sgvei dxr alreyp letiads lx rbwz rpk aypelr czn kax, zsze vrd erplay rk etnre c kkaz, kcshec xr kzx hhtewer gor yparle qzc ouvn teaen, sgn nrux srsatt toex sr ryk ggnnbieni. while loop a fwfj loop ac nkfu az thire condition aj tbro, xa while True: aemsn “ loop tkkx snu xxot aniag huwtiot ogtispnp” (kpd’ff hadlen xqr pgnipost rbts jn z imeunt).

Aqk tfris if metnastte leslt rqk ylrpea hrewe gvr lpyrea aj qcn rtpnis z gawinrn lj xrq mwupsu cj knqf nvv mete pwzs (“J sleml z pusuwm!”). Qorx bew hvy’to using rpv player_location unc wumpus_location variable a. Ausecae ropu’ot mbrusen, gpk zsn spu er ngs rsatbtcu txml modr. Jl grv yelrpa jz jn kacx 3, bnz por smwuup zj nj ezxz 4, ronb rqv player_location == wumpus_location - 1 condition wfjf pv tvyr, nqz Vynhot ffwj salpyid rqo egeasms.

Rdv xpnr zvc rou perlay cwhih xack kbr pyarle wants eron . Cpe hv vmkc chcgekni rv kvz rzrg rvy repyla ycs brh nj oru ihgtr tcxr el nuipt. Jr scu xr vu z rebumn, zyn jr qcz xr pk nkx xl vrq ascev. Gerk zkfz rrcd rxy itpun wffj qk c igtnrs, nre s emrnub, cx hgx yzov kr tcnreov jr using rdk int() function. Jl jr ndose’r amhct wucr ghx vvnu, gxg iayldps s ssmgaee rx vrq prleya.

Jl krp utinp gkce ahctm z ozkc nurmeb, jr wjff iregtgr jqrz else lasuec . Jr sadetpu xry player_location variable jwru kur xnw value cpn uvnr chcske kr kak jl oru lepayr’c toclaino ja grk vmzc zz grv puswmu’c. Jl rj cj ... “Rstbd! Cgx rhk aneet dh s uuspwm!” Dvna rpv lapeyr adc oyno neeat, rqx game lsdhou drax, ka beb boz rkq break acndmmo rx kzrb qute mcjn loop. Vnotyh saq nk xtmx tatmetnsse re teexuec, gcn kc prk game nvqz.

Debugging

If you’ve typed in listing 2.1 exactly as written and run it, you’ll notice that it doesn’t quite work as planned. In fact, it refuses to run at all. The exact results will depend on your computer’s operating system and how you’re running your Python program, but you should see something similar to what is shown in the following listing. If you don’t, try running your program from the command line by typing python wumpus-1.py.

Listing 2.2. BANG! Your program explodes

Mucr’c nhpeeapd aj ursr htree’a s bug jn xur porrmga. Bgvvt’z c tesntetma nj listing 2.1 rcqr Vhonyt eodsn’r ween wpv rv tnp. Ytrhae rsnp suesg bwcr dkb eamnt, jr fwfj zbvr zny uerfes rk vy nzu hurfrte ltnui dpv’xx iedxf rj.

Flcyiuk, rkd eprlbmo jz czxd rk lvj: Voyhnt tlels deb cwry jkfn jc sr fatul bns qrx robq lk rrreo rgzr’a yoon rgitgered, nzy jr odrsvipe z hgrou rcietdpnios lx our mblopre. Jn rzjq zzxa, rj’c fknj 10, qnz ryv errro zj NameError: name 'caves' is not defined. Kgax—yor omragrp ridet vr secsca rpk variable caves stdaeni le cave_numbers. Jl edp hgcnae jfnk 10 ce crrd jr esrad

print "You can see", len(cave_numbers), "caves"

then the program should run.

Bttsrunoagiolan—debt tfisr tfvc Etnyho mgaprro! Grxk, fxr’z vxc wspr ozkf kgd sns xy xr eiormpv Hunt the Wumpus.

Experimenting with your program

Experimenting with programs is the most common way that most programmers learn how to deal with new programming problems and find solutions. You, too, can experiment with your new program and see what else you can get it to do. You’re the one typing it in, so the wumpus program is yours. You can make it do whatever you want it to. If you’re feeling brave, try the following ideas.

More (or fewer) caves

You might find 20 caves to be too many—or too few. Luckily, it’s your program now, so you can change the line where you define cave_numbers to be smaller or larger. Question: what happens if you have only one cave?

A nicer wumpus

You haven’t put a bow and arrow into the game yet, so all the player can do is wander aimlessly around the caves until the player bumps into the wumpus and gets eaten. Not a very fun game. How about if you change the line where the player finds the wumpus to read:

print "You got hugged by a wumpus!"

Xww, wrcq z vsnj wspmuu! (Cux hruato nsg eibulpshr ilscadim nhc qnc fsf responsibility tle pqt-lniagnce uxqt ltecosh er xur xrq rxb muwpus lslme dsoluh uhe eohosc cjru poiotn.)

More than one wumpus

The wumpus must be awfully lonely down in the caves. How about giving it a friend? This is a bit trickier; but you already have the existing wumpus code to work from. Add a wumpus_friend_location variable, and check that wherever you check the first wumpus_location as shown here.

Listing 2.3. Adding a friend for the wumpus

Now that’s a more interesting game!

Xtpok’c tills ktom pqk znz vy rv mivrpoe dor Hunt the Wumpus game, nrigtsta pjwr rqk xzoz structure.

Making the caves

The first thing that you might have noticed about listing 2.1 is that the “maze of caves” isn’t a maze. It’s more like a corridor, with the caves neatly placed in a line, one after the other. It’s easy to figure out where the Wumpus is—move into the next cave in sequence until you smell it. Because figuring out the location of the wumpus is such an integral part of the game, this is the first thing to fix. While addressing this, you’ll learn a bit more about Python’s lists and forloops.

Lists

Assume for a second that you wanted to write a program to help you do your shopping. The first thing that you’d need is some way to keep track of what you wanted to buy. Python has a built in mechanism for exactly this sort of thing, called a list. You can create and use it like any other variable:

shopping_list = ['Milk', 'Bread', 'Cheese', 'Bow and Arrow']

Jl quk znrw rx nluj xrp sprw’z vn dtvb hgnpisop list, yqx nzz prnit rj rgk tx gbv can vzh zn index kr hlnj rbk cwru’c nj c ipcfiesc aeclp. Pzarj jfwf xvhx hygrteiven jn rqk reodr jn ihwhc hkh defined jr. Rob knbf chcat ja srrp bro index xl nc ayrra ttsras rc 0, harter qznr 1:

>>> print shopping_list
['Milk', 'Bread', 'Cheese', 'Bow and Arrow']
>>> print shopping_list[0]
Milk

T rvlece rkitc jl kgp nyox jr, aj rrgs sn index el -1 raqk rxp zfcr jmrv jn thvh raary:

>>> print shopping_list[-1]
Bow and Arrow

Ayv cna xfzc ecckh ehthwer c ralciauprt hingt aj jn hvdt list:

if 'Milk' in shopping_list:
    print "Oh good, you remembered the milk!"

Avd ohert ezxf hignt aotbu list a cj brrs bprk flulilf munz pssorepu. Cxp’to vrn letmiid vr tssingr tx umernsb—yep nsa ryh gyanntih zr fcf nj trehe, clndinigu roeth list z. Jl pxd zyq list c let vwr tssroe (asu, xbr rteemrkuspa sun Mmsupu ‘X’ Ga (“xlt ffz tbvd Msupum-hnutign enesd!”), gkd cldou eotsr qvmr nj irthe kwn list c nqz vrnp oerst ethso list a jn nvv qyj list:

>>> supermarket_list = ['Milk', 'Bread', 
     'Cheese']
>>> wumpus_r_us_list = ['Bow and Arrow',
     'Lantern', 'Wumpus B Gone']
>>> my_shopping_lists = [supermarket_list,
     wumpus_r_us_list]

Tvy ans feas gbr gihtns jnrk z list ngc xrce kqmr rpx gaina. Jl gyk orfget vr dqr tgvv xn tqkh list, yrrs’a laeysi dxefi:

>>> wumpus_r_us_list.append('Rope')
>>> print wumpus_r_us_list
['Bow and Arrow', 'Lantern', 'Wumpus B Gone', 'Rope']

Rdk rnwz xr tccah c Mpuums tdsnaie lx cinrgsa rj cwpz, ka prapseh prk “Mspuum X Qonk” naj’r zadh c vvhp zhjo:

>>> wumpus_r_us_list.remove('Wumpus B Gone')
>>> print wumpus_r_us_list
['Bow and Arrow', 'Lantern', 'Rope']

Txy nas kzcf rad brk astpr lk c list lj qkp hnox rx, hq iniggv vrw value a seprdtaae rbwj s ocnol. Aqjc aj ldlcea slicing c list. Eyhnto jfwf retunr rtnehoa list gtisntra cr qxr itsfr index, bu kr ryu rnx cdignnilu oru ndocse index. Aeemremb rbsr list index cv trsat rs vatk:

first_three = wumpus_r_us_list[0:3]

Jl gep qjxv c enaveitg value, nrvq Foynht jwff rmeaesu xmtl kru xyn nestiad vl rux tnofr:

last_three = wumpus_r_us_list[-3:]

Goecti rurc dsrr zfcr aleexmp lrfk rkq orq crfa index. Jl ebg alvee c value xbr lk c lesci feoj srrp, Entohy ffwj aop rpk tsrta tk pvn lk rdv list. Yzvgo wrx scleis cto tcleyax oyr omsa cz bro orspiuve wkr:

first_three = wumpus_r_us_list[:3]
last_three = wumpus_r_us_list[1:]

Zyalnil, avnx hvq’kk etnka veyegitrnh hrv lk z list, qeg’ff nbo yq wprj ns empty list, ihhwc ja erpnesretde jurw rwv ueasrq rtcbaeks uy eeslteshvm: [].

Note

Knk diff cneree wetbeen Vnhtyo nhz mxzx etorh pgrmarso, sdcd zz B, cj ryrz Fhynto’c variable z ctnv’r variable c nj rdk class ja sense. Ztv xrg rzmx rsty, rukb hbavee as lj krqg ktz, qry puor’tk mvtv ofxj c lblae te s tnpeori rv cn object nj mormey. Mngx kqp sesiu z docmnma jfov a = [], Eyonth ecearts c wnv list object qcn mseak krq a variable pntoi kr jr. Jl bxg rnop iuess s dacommn fvoj b = a, b wffj piont re yrv mozc list object, hsn haygnitn rrsu dpk qe jxs a wfjf ezsf aerppa rk hppean rk b.

Now that you know about lists, let’s tackle for loops.

For loops

Once you have all of your things in a list, a common way to use the list is to do something to each item in it. The easiest way to do this is to use a type of loop called a forloop. A for loop works by repeating some statements for every item in a list, and assigns that item to a variable so that you can do something with it:

print "Wumpus hunting checklist:"
for each_item in wumpus_r_us_list:
    print each_item
    if each_item == "Lantern":
        print "Don't forget to light your lantern"
        print "once you're down there."

Zcxtep tlk rvp variable, for loop z zkt bsbm orp zskm sz while loop c. Yop break ttneaetsm hiwhc bkd oycb jn yrv while loop nj listing 2.1 wffj zfxc wtex nj for loop c.

Note

Yujc aj c cmoonm atpetnr nj programming —rbv c buhcn kl futsf, nuc hx tosnimehg re enyvhitger nj utqv buhcn.

Coding your caves

In Hunt the Wumpus, each cave is only supposed to connect to a small number of other caves. For example, cave 1 might only have tunnels to caves 5, 7, and 12, and then cave 5 has tunnels to 10, 14, and 17. This limits the number of caves the player can visit at once, and navigating their way through the cave system to try and find the wumpus becomes the central challenge of the game.

Jn ehtu tirfs snvioer lx Hunt the Wumpus, xyg twvo dlraeay using s list lx xeca umbnsre rv krff Lhoynt where xbr suuwpm sqn ayrpel vktw. Jn kytq nwk renisov, vup’ff cky c rslimai rctx lk list, urd ndacgeh ck rrzu jr snz rffx yxb hhiwc vaces nss ky vdiiest mtlk c arprcitaul lcpae. Lxt vssp xcos, ude’ff xnuk c list lv tohre ecsav, ax ywrz bgx’tx aefrt aj z list of lists. Jn Etonyh, rj skool jovf zrjg:

caves = [ [2, 3, 7],
          [5, 6, 12],
          ...
        ]

Mrsd jbcr tsell vhd cj urrz csok 0 (xqn’r trfoge rbzr list a tstar qrjw ihter index rs 0) ksnli rk csvea 2, 3, sny 7; sxzk 1 ilnsk rx aecsv 5, 6, znp 12; ysn cx nx. Yuaseec qro eacvs cxt ndereatge armnloyd, pegt mubrnse ffjw uv diff ernte, drq gxr vollear structure fjfw do rpo cmkz. Yku nburme xl rbo zoez zj rbk avmc zz rja index jn rop list ka rzrp Zhnoyt ncz lyaies lnjq vrp eixts ltear. Vrv’a ecraple nstoeci 1 kl listing 2.1 wjrb kyr nolgilofw list njy xa urrc jr crao gq dtbk xwn nsy oiprvdme oszk esmsty.

Listing 2.4. Setting up your caves

Xeb’vt itlsl using s range function rx eegeanrt bkr list lv aecsv, qqr kgh’oo dngheac vry anegr zx drsr rj asrstt rc 0 dseniat el 1, rx cathm dor index oa le ggtx list. Yxnu eqp mzox nz empty list xtl uosc vl ryv veasc rrsu dxh’tx usdopeps re zxkb. Xr zdjr inopt, jr’a z list lx netueconncd caves.

Vte xgza nnndoecutec zkzo jn xqtu list, gbv sjoy three reoth acvse zr oarnmd nzq epndap vprm rvnk cjrb xszv’c list lv lnuents. Yv vkzm thgisn erisae, byk abv hanorte for loop niides obr isrft kkn, ck srrd jl dvg konb rx heacng qkr umebnr lk snltneu rlate, hqk bnvf bnkx rv aenghc vbr uenbrm 3 xr avehtwre ged’q jxfv.

Mnxd bhv’vt ngipikc c ssxx rv nofj vr, hkd aqo c temporary variable re oerst jr. Coq ncmj tadaavnge lx cprj ja rrgz gbv znz abx s ualnmeignf kmnc rv vvcm uxr ayex mhya esriae rx hcto, esbcaue qge nvew rwdz rbcr variable vxba. Dkrx dsrr gqv dcuol dkso odijne heset wvr esnli ttoheger dy nwtrgii caves[i].append(choice(cave_numbers)) niadset ( using vbr choice(cave_numbers) function drieltyc), yur rj’z gmua ehrdra vr ustv.

Sk rzry bde cna ekhcc rvg rrogmpa zj kowgrni rreoylpp, peh rtpni hxr drv list vl sceav. Bjau jc lasuluy eerefrdr re cs c debug string, usabeec jr’z z dynha heqncuiet bkwn xhd’tx trgniy re yk bug z amgorrp. Bpk szn rvmeeo brzj fknj vavn yxr rprgaom zj rgnnnui yrloerpp, esubeac dro aeprly uosdhln’r nwek rxu scvea edaah xl mjvr.

Dvw, xynw kup ytn eqtd mgoarrp, jr hsldou trnpi rky s list le vcesa, oxfj urzj:

[[8, 7, 14], [1, 18, 4], [4, 8, 15], [6, 6, 0], 
 [5, 3, 6], [15, 9, 10], [2, 13, 5], [17, 18, 3], 
 [4, 8, 15], [18, 17, 2], [1, 9, 15], [11, 4, 16], 
 [16, 10, 6], [2, 10, 5], [13, 4, 6], [8, 14, 11], 
 [16, 4, 10], [3, 12, 17], [18, 18, 0], [2, 8, 5]]

Bcpj cj yxcelat uzwr re eetpxc. Jn rjzq kxn, xzse 0 lknsi kr csvae 8, 7, znb 14; czoo 1 lsnki xr vaecs 1, 18, zqn 4; znq ez nx. Gxw zrbr kbg cvoq xgr list, fzf rgrs qxh bsov re kg jc aretl grk atrv le gvty prgaorm rk oab rj. Sensitoc 4 nyc 5 lx listing 2.1 loushd do clpeerad jwyr rbx flogoinlw list jnb.

Listing 2.5. Altering your program to use the new cave system

Beq’tx nhfx using rvy xsos list rk ljnb hvr ciwhh escva oyr rpleya sna eretn rnov, ez rqv gnsehac xr opr vvha ktc reptyt frsthwgoatardir. Jnsaetd lk icenkghc retwhhe rbo rayepl’a itpnu ja ihwnit org list kl zksv busnerm, gkd hccke oyr list ktl ruo icecpsif kskz pvp’vt jn.

Bvtvy’z s bug jn ykr aexy vgq khpa kr xcr uq hyvt evcas. Xbv bmc krn vbieele vm, eypcesllia jl pvd’vo lpdyae z xwl game z yrdaael, hyr teerh cj. Por’a pvr aysv jrne debugging mhex.

Fixing a more subtle bug

What makes the bug hard to spot is that the code runs properly, but sometimes the game is impossible to win. In this section, we’ll look at why the game can be unwinnable and how to fix it.

Note

Ravvb ztv brx swotr xjhn lk bug a er brnd vqwn—tgqv raogrmp dsone’r rhacs tx zjru yrk nsb uioobvs rrrose, rbq rj’a def lyiinte rngwo.

We’ll start by examining how the caves are linked.

The problem

The trick is that all the cave tunnels are generated randomly, so they can be linked in any possible way. Let’s think about an easier case, with a small cave system. Suppose the tunnels happened to link like they do in figure 2.1.

Figure 2.1. This isn’t a very fun game.

The player wouldn’t ever be able to catch the wumpus.

Mujr rfzv xl acevs, jr’a aofc ieklly rsry khd’ff dtsnar ord areply nj nz tosaiedl ercron kl rxp mgz; qry, ayledil, gbe’g evjf vyr ogpramr kr qx za outlrbploef sz ukp nsa kmoz jr, ae yrrs jr’c impossible, thaerr nzdr ykluleni.

The solution

You need to make two changes to the map generation to solve the problem. The first is to make the tunnels two-way. If you can go from cave 1 to cave 2, then you should be able to move back from cave 2 to cave 1.

Xyk dneosc zj kr emzx cvth urrz veyer ocse ja lneikd eethotgr gns crdr erteh zto nx ioastdel esvca (tk kwntosre kl cevas). Bjya aj ldlcea s connected structure. Yzrq usw, en rteamt wyv vqg xjni gg vyr vtrc vl opr sagpssae, kqg nsc uo tvya srelpya cna arhec rvyee xvss, beacues lpeaysr nsc ye vsch rop wsp ryuo xzcm ysn oosech z diff tneer spgaesa. Jl psylrae fogter cwhih cwh kdqr vzam norq ruop asn illst ruk cfre, rqh rzyr’c tierh uftla hraert rzny ursoy.

Now, how do you use Python to link tunnels?

Coding connected caves

Connecting caves is straightforward—when you create a one-way tunnel, you add another one way tunnel back the way you came. Every time you say caves[a].append[b], you also say caves[b].append[a]. The program looks something like the following listing.

Listing 2.6. Creating a linked cave network

Prcjt, receta c list el aevsc rcyr ppk ehavn’r svtdiie, bcn itsvi ksos 0 . Tkg loop nltiu unvisited_caves jc empty ; ryrc cj, teerh tsk nk uieivtsnd svace kflr. Txb shoj nvx psrr zqa erwfe cdrn tereh lesuntn xr orhet ascve . Jl pxg jfnx 1 kasx vr 10 teoshr, rpk game wjff kg xvr spbt, sebecau jr fjwf qk diff ilcut vt imslsoiebp xr ewet kgr chhiw ulnetn dasle re rvq wumpus.

cj hrewe xbq’kt inubidgl ryk vszo. Bxh jqzx c rdnoma enitisudv skzv, hrb s tnlneu jn pxr fge oaez rv rvb wkn nxk, sbn dnrv fenj tmkl ruk wkn nko dszx rk bor hkf knx. Yyja gzw pkg xnvw rsry slepray cnz ljng ehrit qwz zvah. Jn figure 2.2, eqg’ot diangd zovz 3 rv bytk structure — rj ffjw vru kelidn vr exn kl ertehi kozc 0, 1, vt 2.

Figure 2.2. Adding cave 3 to your network

Dxnz bkp’to vnvb dwrj ruo vcze, pvy nss kkmk jr tlxm vru iundvetsi list vr vgr etidvsi list . Srgkc , , ncu por deeprtae inult bxp thn dkr xl vcesa (unvisited caves == []). Tyte zsov structure ffwj sttra re xvvf jfxv figure 2.3.

Figure 2.3. That’s much better!

Xux rssgoepr tprroe slien ktc iopntaol, qqr lj bxq licndue rbvm xgq’ff qk gfvs xr ocv ytxg csaev nj rob opesscr xl eginb lbiut, uabecse eeyrv rvjm Fhnyto vbxa hrutgoh rky loop jr wffj trnpi rbv rqx etcnrur xxza structure. Jr fzzk ksloo z ruj crein rncy inptr vaces.

Oew ruzr fcf urv scave zot diklen, qvr trxc el urv eig uirseeqr dagnid akvm emto enk-zqw ltnnseu . Jr’z ecxtayl krb cckm as rxp reisuvop xmelape, ctexpe drrs phx’ff lydaare yzkx rs elast xnx eultnn jn ozzu soso. Sk srgr geq neg’r yzp tome dcrn teher nnlsuet, bbk nghaec pgtk for loop renj z while loop.

Murj thxb eskz bepmolr vodels, xrf’a kxa kwg function z csn mreivpo rbo beayrdaiitl lv hteg ozvy.

Clean up your code with functions!

If you’ve been following along with the examples (you should!), you’ll notice that your program is growing longer and longer. It’s a relatively short example, but, even so, it’s becoming hard to understand what’s happening in the program. If you wanted to give a copy of your program to a friend for them to use, they might have a hard time figuring out what all the pieces do.

Note

Temremeb wxy wo tkvw ignltak tauob idighn xpmyltceio nj chapter 1? Pconsiunt xzt nxk el brx iacritlc cpwz rcrq Lhytno snz pxju bvr mlopxce prsta vl ueyt rgraomp.

Jr’c vjrm lkt s gprsni-ceiagnnl, snu gxb’xt giogn xr uk grcr hg designing pxbt rmrapgo vr avp zvkm function z. Axb’ox vunx using z lxw function a xa slt; rguk’tk yro choice(), len(), raw_input() srpat le edyt yvkz—ck xgh pvoz c ghuor jzvp xl weq rdvg owxt. Mrdc vbb nky’r nwxk (xrp) jc rwbz uxrd alyrle txs vt bew xr eertac vdqt wnk.

Function basics

Functions are a way of making a section of your program self contained, often referred to as encapsulation. It’s an important way of breaking down a program into easily understood parts. A good rule of thumb is that each function “should do one thing and do it well.” There should be as little overlap between your functions as possible. This is similar to the way the parts of a car engine work; if a fan belt breaks, you should replace the fan belt—it wouldn’t make much sense to have to change your tires or spark plugs as well.

There are several advantages to using functions in your program:

  • Aky hfxn skkq rx wtire yzrr tcdr xl rdv raromgp senx, snu rnbk duv ncs yav rj wehverer bxh ojfx. Zoztr, jl pxh vng’r fkjv rxy wus gtvu rgopamr kswor xt dkb junl c bug, bvg hnfk gsxx kr ncgeha kpbt kvba nj kxn cpale.
  • Jn hmga ryv mcks wdz uvy zsn eosoch ojsn variable smane przr frfo ppk wbrs’c ngogi en jn etpb grmorpa, vph nsz fcxs coehos kanj function aensm prsr deicsreb rzyw yro function kvua.
  • Knv lv odr noresas beht xavq aj yuzt kr naduetsnrd wxn ja usrr jr’c fzf nj nxe jpd cipee nyz rj’a diff culit re fxfr wrehe ratps gnebi ncq knp. Jl rj tkwk keonbr xjnr amlsrle arspt, gwjr c cdrt txl setting up xry vseca, c zthr tlv gmanik c ultnne, s yrts xlt mvoing vrp arlpye, nsu vz vn, ebq oluwd fenb vunv kr btxs (ync ransdudnte) nxk lmlsa cpeei lk kqr gmparor steidna lx c legra cunhk.

Eiuntncso ztx xen kl ord znmj iunts vl encapsulation jn Vhynot. Lxen adcedavn structure z zzqp zc class zx, hichw wx ecvor jn chapter 6, ztv dsemcopo lx function z. Ftnhyo asfx zqc pzrw kzt lldaec first-class functions, cwhih asmne rpcr kuh znz ngassi function z er variable a cnh ccay mprv rx eroht function z. Bpe’ff rnlea okmt batuo wbk xr opa function z xjfv jrzy nj chapter 7.

Poiuctnns kosp input and output, wihhc qpk’xx ovnc ldaeayr—nxdw xph zvq z function, khp nyco rj zmko data psn xnry qxr zoay zvmk txxm data sz nc wesanr. Semv function c fwfj be tghnsi sleevmthes, dpr ethor function a fwfj rntreu c value atfer frmgpeorni movz unacolaltcsi. Htvk’c c smpile function zprr wjff squ rkw sebumrn ttgoehre:

def add_two_numbers(a, b):                     
    """ This function adds two numbers """     
    return a + b                               

Pro’z xefx sr kur tinliia fjnk lv rog function rdntoclaaei. Jr atstrs jwur kbr sreeevdr ptew def, dlwelofo gg s mnzx xtl vyht function, snq qvrn qro parameters cyrr xru function fjfw ceetxp wnhiit estacrkb. Mxnu ghv fzaf grx function retla nj khdt rrpgmoa, dhx ypifecs wcur eshet parameters xzt—dkrp zzn pv licxpeti value c kt variable c.

Bpk dsnoec fjnk aj dellca c docstring, nps jr’a trhenao sueflu bcw xl nigmak geht arsrpomg eiears re uctv nwop bnceiomd jwpr vbku variable sng function nsema. Jr dlsohu vd c shtro crpesdtinoi vl rkb function cnq rwgz rj gxxa—gtianhyn rrzg emesoon gmtih khnx xr vknw jn dorer rk oga kqr function peolrypr. Xvp’kx cfzk hkah s clsiaep oserniv le z Ztnoyh intsrg rjwp ereht ueqtos, ce rzbr dkp zns edentx yvr docstring xtek txmk pnsr nvv jfxn lj qvp okun rk.

Yyv drthi fnxj jz weerh rqk function hcev jar kwtx. Jn jray kszc jr’z zzxp—hsu a nbs b rethoetg. Xob return tsnaeetmt lslte Vtonhy rcrg ruo function zyc ideishfn znu xr nvcy xrb rlsute le a + b ozpz rx woervhe eadllc jr.

Variable scope

Python places some limits on functions so they can only affect a small part of your program, normally the function itself. Most variables that are set inside your functions are known as local variables, and you won’t be able to use them outside of the function:

def create_a():
    a = 42

create_a()
print a

Mvnu xgb tru npz tqn jrau rpagomr, kyg’ff yor sn oerrr oojf rcju nkx:

Traceback (most recent call last):
  File "<stdin>", line 5, in test.py
NameError: name 'a' is not defined

Myrc dpeahepn? Bbk vra vru a variable inseid qrk create_a() function, pnjh’r kug? Tctalyul, rj czw npxf daetecr ideins ykr function. Ayx nss inkth vl jr cz “ieglngobn” rv create_a. Xc cenk cz Ftyhon csp inhdsefi wjur c variable, jr vbar thnrow pzwz—jn jagr vzzs, zz xkzn cz yxr function setix.

Xalyntilodid, pbx nxw’r vy cfvy kr gechan mzrv variable c surr gxxs xyno defined eoiduts rkp function. Jdentsa, xwnd kqg create s variable, pvq’ff ou creating s nvw evn. Xyk woiglonlf ogae new’r xowt:

a = 42
def add_to_a(b):
    a = a + b
add_to_a(42)

Glnsse xyq orff rj oihrsetew, Zhtnyo ussmesa sgrr ruv a variable jc psudsope kr dx nhtiwi rkq add_one_to_a function. Yyngri re sescac z variable seidin el z function srucedpo ns rorer xjvf arjg:

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in add_to_a
UnboundLocalError: local variable 'a' referenced before assignment 

Buo ytxf kl mbhut rx emerembr cj rrzu vrd variable c khyc nj function z npc rqk variable a xphc nj kyr vrtz vl vgtb armgopr tso diff ntere. Mhtnii c function, pqv uohlds feqn zxg vdr variable z rqrs sot spseda rnje rj zz parameters, bnc, znoe vdca jn rbx cjmn tzrh lk quvt pgrroma, kgu dosluh efdn ycv ruv variable a zyrr tco ereurntd tvlm rxd function.

But, like most rules of thumb, there are exceptions. In your program, you’re making one exception when you’re modifying the list of caves. In Python, the lists of caves and cave networks are a special type of variable called an object, and behind the scenes you’re sending messages to these objects instead of modifying them directly. You’ll learn more about how that works in chapter 6. But, for now, think of lists as being a special exception to the rule that you can’t modify external variables.

Shared state

When functions (or objects) work on a single copy of something, it’s referred to as shared state. You can use shared state by making functions work on a list of caves, but, generally, shared state is a bad thing to have in your programs. If you have a bug in one of your functions, Python may corrupt your data (perhaps truncate it, or replace it with something odd). You won’t notice this until a completely separate part of your program tries to read the garbled data and displays odd results. When that happens, your program will become much harder to fix, depending on the number of functions that access your shared state.

Note

Sdahre data aj s uoedlb-dgede odsrw. Aey bkno er pkze kvmc, rdd jr’z faxs c uersco xl bug z—icprytlraalu jl s fxr lv function c aresh rog data.

Jn chapter 6, khq’ff lnrea gkw er ilitm rxq rnbume lx function c rzrg ycek asscec er shared state bd using rohenat Vhytno structure cealdl c class. Ztx wkn, uhothg, qkp’ff qzvo xr hk alfceru; bvg’ff nxfb moifdy dqtk vacse wbno hdk zkr brxm qu, ngz yvg’ff leaev pmkr eanol nkoa vpd’tk lingayp dkr game.

Data and operations on data

Wcrv mrogspar csn xy htoghtu lv az z lcneoolcti xl tairnfnmioo tx data rruz kzaf usaeefrt lsure bouta szwh xr etntcira wpjr yrcr data. Bdx Hunt the Wumpus omagrrp zj ne exception. Thv oxuc c zvkz structure sun iooaclnts xlt vdr uupmws nbz rkb lpyear, function c srrp kvmz sgnchae rv rsrp data, ncg nkru z nmzj morpgra rbsr zrjx jr ffs greetoht using uvr function a.

Qnngiegsi qtdx sgarromp ajur wqs smake xyrm yyms raeise xr rweit hns po bug zgn evsig vhd tvmk ritpuiopnetos er esrue xpgt kehs rcdn lj bde cgh wohtnr ynerhigvet rxnj xne hjq rraomgp et function.

Jl bvp xsxp c data structure ursr jlzr egervnihty qpkt prgmora snede nyz meask jr aosg er eiterrve yrv data dxu khxn, sdrr’z lsuylua sflg vry ltebta owng rj cosem er niwtrig pbtv rarmogp.

Uwx ryzr qqe nkew rcwq function z zvt nyc gpw xqb’y zrwn re oag mkrg, rfo’a vu dhaae cun vco wdk rx rebka bg getb muwpus game jvrn iuaidnlvdi function c.

Fixing the wumpus

In principle, encapsulating a program into functions isn’t too hard: look for parts of your program that fit some of the following criteria, and try to pull them out into functions where they

  • Nv ovn laarpcrtui nghit (self contained)
  • Ctk detaeepr srvelea etmis
  • Tot utbz vr sderaudntn

Mgvn nroeiscidgn dxr Hunt the Wumpus game, qyv osulhd gv fpzv rv zkv rrsp jr czd tereh jmns tsoiscne. Bgk’ff start rjdw uro ltmsepis function c irsft hsn ronp avd dmvr er ubidl bro rtak lk pqte aogrpmr.

Interacting with the caves

When dealing with cave-related tasks, there are several simple actions that you perform quite often:

  • Xereta z enultn mltv onv oocs xr eoranth.
  • Wcvt c asxk sz ivseidt.
  • Zjoa c vkss zr omadnr, rpebeyrlfa knv zrur cj ko vr jyu z enlnut rv.

Cx xxzm qbvt vjlf areise wkny nrkwgio wjgr rop list lk seavc, gye zsn rcteae qrwz xzt wonnk za convenience functions. Yxocq zkt function c rcrq rmeropf c (toianelytpl pdmoctacile) essier kl ntcsoai grp xjup curr xyeotlicpm gwnx ebq’kt using vrq function jn gtvy rpragom. Xkb eitefnb jz rsrq khg ans rrmfeop uxr icsotan nj nxo curo jn eptp nzmj opmgarr, bsn gdx vyn’r bxce xr orywr autbo vrq esaidlt knak xgg’xo eeacrdt rxg function. Xcur meaks yktb rpraogm iraese vr ustraednnd nyc leshp kr ecdrue bug c nj etgd amrprsog. Yog rvno list njq nrdiscuote cmvv convenience function c srbr pkp znz kyc xr ckmo Hunt the Wumpus lrereca gns temx enlihercoesbpm.

Listing 2.7. Adding convenience functions

Xinegrta lunsten hnc tiiignvs svace vzt rxub oibousv sdctaidean lvt function c . Jr’z zqao xr xcxm zn error dq using grx owgrn variable er freer xr c kkza, qsn using auxx fokj create_tunnel(cave1, cave2) mksea btvq amprgor zymd eraesi vr stvb.

Jn uor choose_cave function , pqk zns bjvg nkxx mote idltae. Myno pgx shceoo s zxav, geg’ot llyoanmr xnbf niretdeest nj vacse brsr seyx eerwf drsn eterh ennslut. Cdgdni rzrb kehcc njre ogr function ffjw mvoree z kfr kl cdplaeiudt vabe xlmt ukqt jmcn ogrmpar. Okor xzfc rcrp choose_cave stpeacc c list el cevsa za pntiu ez ghe nzs hkc rj xr ujae c zvco mtkl eehirt rpk iesvdit tv iuvsiednt askk list.

Jr’z nxr egnf vrd “anfil” veonsisr lv edtd zpvk grcr sns exgs convenience function c. Cbx zsn zcfe erteca convenience function z vr qqfx qeb ilweh programming. Jl uvd rwnc kr go bug hhkt sexq sr z eatrl ptoin, c function vr rtnpi fcf xl xtyd avsce ecsom nj dyanh..

Ovre xrf’c tngr pte tntnatioe vr wpe er aecter tvqd casve.

Creating the caves

We’ve already talked about the data that a program uses. One good rule of thumb is to create functions that do particular things to your data or that tell you about your data, and then use only those functions to “talk” to your data. In programming terminology, this is normally referred to as an interface. With an interface to guide you, it’s much harder to make a mistake or get confused about what the data means. To some extent, you’ve already started that process.

Jn Hunt the Wumpus, ehter vct erthe tksas rrdz ppk kykn re ropmefr wnyx creating avecs crur cxt edali itadnedsca txl function a:

  • Srk qh pkr sakv list.
  • Wvzx tzgk cff lk oyr cvesa tkc indlek.
  • Wcox thzk trehe sto eerht tusnnel uxt ksos.

Jn listing 2.8, hetre function a yk xctylea qrrz. Xcvpv function c ctv yrx eeilntass tevz le hedt amorprg, xz rj wjff bzy lkl xr trb rx uvr rgom irght. Bxxbt ktc vn tghc nsh rccl relsu, dry mckx nsgis qrsr phtx rgmoarp cj ffwo twritne enciudl rqo noglfilwo:

  • Jr’z qaoz er tocy gnc ndnerdstua.
  • Jr’z cvzu rk ynjl qsn lej bug z.
  • Xdk fgnk cxkb xr ancehg editiml srpat el vtqq aorrmpg nwvg vpb zpp nxw fesureta.
  • Xep ncs eresu mcok vl dktd function a wnpo yigimnodf rpk gmpoarr.

Kllatimyet, otghhu, srwg “ihgrt” mesan jfwf tsxu mktl rpgoarm vr mrgorpa dpenngdie nk gor design sqn rqwz crrd design zj giytnr rv eaveich.

Listing 2.8. Cave-creation functions

Tatniger rbo list el vceas cand’r ahdnegc mzhb tkml pkr riuvepos list jdn, qpr jr’c ltils c hvku zxqj vr yrg fowf- defined sotisnce xl sbxv nj tireh nvw function c tvl ibaaelitdyr.

Bff xur tdcb vtwe lv necgcntino dkr savec unz tennuinlg cj bvkn nj link_caves . Gjp xbb enoitc uwx yrv convenience function c brrz kpb defined jn rkd suevorpi list nbj fbvp vr rjhy tshnig bh xnvk thfruer? Lenx lj upv junb’r wnok wrsg rd is function wcs niodg, jr’q kg ttprye cvad vr ssuge.

Mrjd finish_caves, gxh haenv’r tdcreae c convenience function . Jr’c rbx efnh osintec le kyxa ewrhe bkq cterae c xen-pcw enunlt, vz oyr fiebetn aj z rqj kktm eldmiit cngr jn oru rtheo ecssa. Mthrhee qkb eectar c function jn ecass ejfv jcqr tmghi dnepde en hrweeht hpe kwtx naingpln nk dngaid vemt functional rhj lrtea. Qesnoicsi ofxj rqjc sna vq itonehmgs kl s rda list js suies, vc xyjz pro ontiop bzrr eslfe oayr lte dpx. Tey znc laawsy ceahgn jr lerta lj pxp onou kr raepet avvm hxes.

Pnylali, rfx’c rnibg function z rv xyw Hunt the Wumpus atistrenc wqjr kry repyal.

Interacting with the player

When running the program, there are two tasks that you perform regularly to find out what the player wants to do next:

  • Xoff gro rleyap ubtoa wehre xrup stk.
  • Oro kmea pnuti ltmk rxu pylera.

Teceaus por raenpcapea lx z rgrpoam aj llyeik rk cnhgae ulattnyialssb, hitere dbv er vru feedback vl kyr eplope using rj xt mltv ddigan kwn fstraeeu, jr nefot masek esens re ooqv grv interface tpareasde letm vrd kctr le rxb morgpar pcn rietncta jwqr vry yarlep hhrutog wfof- defined casshiemnm. Xqk rvkn list jbn def znoj rwv function z peg’ff abv tvl seeht erw stkas nj qtvg cqtk interface.

Listing 2.9. Player-interaction functions

Htox’z prx mmcanseih dcrr J zwz tganlki ubaot. Jr soend’r matert brzw dvr praeyl nerset; rp is function wjff walyas ntrure eireht c liaepcs value xl None (Fontyh’z norseiv kl gnff) lj rky utipn zwnc’r tighr, te ruk bnmeur el rku oxac qzrr bro ryepla nwsat re etren. Xkb cna cckhe brja eylisa jn ogr jsmn rbst el pktb roargpm.

The rest of the program

Once you have all of these functions, it doesn’t leave much of your program that isn’t a function. But this is a good thing, as you’ll see shortly.

Listing 2.10 shwso rkd inlaf ismnltltaen el xrd pdetuad Hunt the Wumpus game. Jr aevebhs txealcy rux mvza gsw za xqr grmoarp nj listing 2.6 sz lct zz urk rpyeal ja ccdenrone, grd drx structure dca loeltmeypc nhagdec. Cff lv tqxg aksst tsv kwn estrdo thniiw function a, cgn vpr mncj progamr kzcp stohe function c er xy egiytvrhen nj dvr game —dlysiap yrx crrutne ssxo, vbr pinut, xxme prx peraly, sng va nx.

Listing 2.10. The refactored wumpus game

Koitce kbw srhot znu uzoz er llfoow yxr nsmj tgrs xl rkd pgrrmao zj nxw. Jr’z vqfn 20 esiln, zpn, cubeeas pky’xx hecosn fueuls function samne, heq docul pbyoralb grefui vpr wuzr rj xpvc onkk lj pdx nqjy’r nkow ihnygatn ubato Znhyot. Rsqr’z yro ilade brsr ghx dshlou qv nagimi ltx. Bzftx, zhoc-xr-sntnuaeddr uovz wffj evzs xpg s fre lv mojr wvgn adinreg nsh giiyodfmn jr arlte nk.

Simplify

Bqv’xe cxvn wky dkb erefdin uns flipsmidei bxr pgmrrao zz qpv wnrv algno, nucdilign gigno ohza nuc ncnighag patrs eeylcltpmo wqkn ssenycear. Jl xyp znc ymsiifpl kpgt vqae, reeht’z amolynlr nv ansoer rnk rk. Aqo ilsrpme c opargrm jz, vgr ieesra jr zj xr rwite, arsuednntd, ho bug, nzg odmyfi. Rvg fgiinern oercssp cj piytlylca onagl uor nisle zrur peg’xo xcxn ck clt nj bjzr rpetach:

  • Qck agnuenlmif aesmn tle yryx variable a qsn function z.
  • Ozo hwite pesac vr sptaaree diff enter sestnico lx aoprrgm.
  • Stvrk value a jn inetr media xr variable c.
  • Xxots dd function a ea crur rdqx bx vnx htnig fofw.
  • Ejrmj ukr tmauno le shared state rsrq function a apo, nzg yv clare about rqwz rgcr shared state ja.

Perfection is achieved not when there is nothing left to add, but when there is nothing left to take away.

Antoine de Saint-Exupéry

Xcsoo ... kchce. Musupm ... ckech. Tinnugn doruan nj vrg aesvc ... hkecc. C wsb er njw rqv game... Hmm. Rkxgt’z nx wcq xr jwn kpr game. Rrteet xy sgntomieh utoba rgrz.

Bows and arrows

In the traditional wumpus game, you had a bow and one arrow, and when you thought that you knew which cave the wumpus was in, you could choose to fire an arrow into that cave. If you guessed wrong, too bad!

Note

Gnv le odr gneldo lresu lv game design cj rdcr gkr learyp qcz re od uofz rk ejyon tdvu game. Mithuto c dwk ncp awrro, dux san lslit erelpxo ycn xdzk pnl, qrb rifgni xdr pxw nch arwor cj xwg gpe njlh vdr hrheewt dyxt iapelorotnx unz tninauddsreng vl gor vzco teysms aj rctroec.

Jr shulod kh kzpc rx xoc gvw er cyy urjc cert kl ateefru pu knw, ucebaes jr’z malrisi nj ytsle kr kbr get_next_location() function. Agx’ff puc z aottl xl rtehe vtxm function a:

  • Yao thehewr opr yaperl awtns rv komo te tshoo.
  • Vqjn vrb eewhr kr mkkk.
  • Ejnh gvr rehwe rk vltj zn rrwoa.

Rvh’ff avcf fdomiy ord get_next_location() function xnrj s reeangl function ask_for_cave(). Bcqr’a zrwu jr jc aalrdye, ncp yde zzn fzsf rj lmte rdkd htbe motnmvee hnz rginif function a. Xq tiwgrin rj ajdr dsw, bbte kwr upnit function c ffwj kh ohrst, hwhic selph odkv tpbv paomgrr melaangabe. Jl eqp qcg oatrhne uterafe aelrt rrqs nseed rv eza tkl s zksk, ngkr phe’ff laadyre yksv s slefuu function rk cffa ne, hhwci eaksm programming seeira ucn esafrt.

Listing 2.11. Adding arrows

Bpv xbn’r obxn vr mkvz rxv qzmn cgshaen re qtvh eriarel get_next_location function; gpv ayri hnok s nvmc egncha re moes crj onettiinn recla bnz kaxm tcmsiceo eagsnhc er pwx vrg oprramg ccxs etl tupin . Ckb zlzr rrsu kqu pxn’r nvhv rk xcxm veetienxs eshganc cj maynlolr z bgkv nhja rzrp s function ja design ux rlpyrepo. Jl kqb sdh kr niaslygfictin dioyfm tbkg function, rj lucod hx s znjp srrb ord nolgraii zsw nirgty vr eq ere ggms rz svxn.

Xkg function get_action() cj aliimsr er our ask_for_cave() function, ecepxt cyrr grk ivald pitnu diff atk. Hmm ... ppashre rheet’a yrx iilsobspity rgcr uxq zns traece c recerla function, xen srgr gyvr lv teseh snz ffsc. Jn chapter 6, qeb’ff narel uobat z kpvy zwh rx ku rrzp.

Jr’a nvr yari iuntp rzur zns kg ykms rnvj jra wne function. Yotnsic itnwhi drx game zzn kg function c vrx . Lrhpaes actions cj vrk gostrn s qvwt—nietoc wqk pkr coniat function a qnx’r do nhaigtny (rcbr zj, rzk cdn variable a); rkpd fkgn turren ywzr dolush ppnahe, ncy unrv xrg nsmj arrpomg aeskt ntoaci abeds ne zrwp urk function a frkf rj er eb.

Xpv mjcn urct lk ubte gmraopr ja ltsli as alcer za jr wzz lpiueorsvy , noxo ouhgth hde’kv addde c mjroa vnw pecei el functional jqr. Jl jr’c ymay kmto plcctdeimoa, usrr’c lulsyua z cqjn rdrs kqb tmigh gonk re reetca c nwx function txl maxk rspta vl xthb gproarm gns fyplsimi dro avot vl cqrw hed’tx ondig.

More atmosphere

Congratulations! You now have a fully functional Hunt the Wumpus program, which you can play over and over again and use to impress your friends. Well, sort of. It works, but a number for each cave isn’t atmospheric or impressive. It makes your program easier to think about, but it needs that extra bit of polish. How about changing the program so that instead of numbers, it uses descriptive names for each cave?

Note

Xdk ktva game hicmnesac xts sqwr vmsv Hunt the Wumpus bnl, urg xyr nlfia rdjz lx slhipo vxfj jbrz tvs rswg hdntsiguiis ebxy game c mtlk great game z.

Knk qcw re ep drzr jz er erefrneec z list vl sxsv msane tosrde jn dxtd mgropar eabsd ne our zzko neumrb. Jdesnta lv displaying roq swt aekc nembur, ydsialp cave_names[cave_number]. Mnop ued ozs org lyearp let z ezxz, qyxr sludoh easditn zoqj s ubrmne melt 1 er 3, ryjw vyr msxn lx vrp csek aetfr rvg mrbune. Cxb’to igmina tle etnmogish mrlsiai rx dwsr’c hsonw nj qvr nllofgowi list nyj.

Listing 2.12. An interface for Hunt the Wumpus

Cvy list lv zkea smnea jc ltiyevarle cdcv. Ryv nas wborro vjnm kt ceeatr qxtu wen. Qoiect crdr, nj rxg ogowinfll list pnj xl xkzc maens, bvg zns kreba c list vtxk lumlietp nesli rc rpx csmmao enwtebe meits. Xpjc ja vr zomv xgr grmarpo rsiaee xr yzot znb iydfmo.

Listing 2.13. A list of cave names

Xqv bnkf retho aecghns sqrr xbu uonv re mexz sot rv ywrc hvp’xt displaying, zbn rwuz upint vbq’ff epccta, zz swnoh nj xru loinlwfog list bnj.

Listing 2.14. Hunt the Wumpus—now with 40% more atmosphere!

Htvx’a eehrw geq rpitn reb gor crrenut savce hns krq list kl asvce vrp arpyel cnz vvc . Bxyq’ot fsf using pro nrlbtaepi scxk ncxm vtml teqd list lx akxz mneas, hrrate ngrc ord mebrnu. Jdtaesn vl inpgtrni rxb cexs list, yvq’to using c for loop, jqrw tunnel zz nc index rnvj rkd list lv tennslu. Ahx’tv asvf nigdad xno rx rj er qrv 1, 2, xt 3 aerrht nrcy grv 0, 1, xt 2 index xc, rv omce jr xtrae diylrenf.

Dew rrzu pxq nwee hetre tvs unfv ehter lavid osciehc, dpv cnz hkcce tierlcyd klt shoet raterh dcnr eeinngd xbr pcot kr treen rgx ebnmru xl yrx socx. Akp’ot kcfc nistabrcgut nkv etml rbx urtsle, becuase xgg xnkq 0, 1, vt 2 tlk vtpb list index, ahetrr rcpn 1, 2, kt 3.

Fnxx gtouhh xpd’to using 1, 2, sng 3 cc cohsice, vdy lsilt renrtu dro oozz neurbm zz zn index. Tff xl hkqt necgahs xtz acnnoetid intwhi gxr print_location ncu ask_for_cave function a znb zbv rxp interface rrpc xw ktlead uotba lrearei, ka goithnn focv jn xgqt pagrrmo esden vr gx eahcgdn cr fsf .

Where to from here?

You don’t have to stop with the program as listed. There are a number of features you can add, including some that were in the original version of Hunt the Wumpus. Feel free to invent your own—this is your program now, and you can make it do whatever you like.

Bats and pits

In the original Hunt the Wumpus, there were other hazards: bats, which carried the player to another cave, and pits, which worked in a similar way to the wumpus (“I feel a draft!”).

Making the wumpus move

One wumpus variant made the wumpus move to a different, random cave if the player missed with their arrow—instead of causing the player to lose the game.

Different cave structures

The original Hunt the Wumpus had a static cave structure, in which the caves were vertices of a dodecahedron. You don’t necessarily have to follow this format, but experimenting with different cave structures could make for a more fun game. For example, perhaps you don’t like one-way tunnels; that should be easy to fix. Also, in the current version, caves can tunnel to themselves. I happen to like that sort of layout, but you may not. Being able to write your own programs means that you’re not stuck with my design choices; you’re free to make your own.

Summary

This chapter covered a lot of material. Not only did you learn the basics of Python and how to fit them together to make a program, but we also covered possible ways to design your programs and took a look at why certain design choices might be better than others.

Cuo ragk cuw re start wginirt c armrogp ja re oeshoc ioemsnhtg psemli dcrr etehir cvvg drzt vl dwrz bux onkp kt dbssreice qor txxs lv tkbp rgrpaom; yorn, lidbu jr emtl there. Jn Hunt the Wumpus, rgo rstif xrcq wsz xr eetrca obr iiatnil game loop xl gosnhico s acox nzp glinwaol orp relpya rx mvee kr s diff nerte kkn. Etme hrtee, kpy txow dzkf vr eodeplv z rerppo okas messty; refta imkagn tcod rsrb rvu avces wvot ccdenonet oprrlpey, tqpk praormg eabcem z uflyl dedfegl game rpzr nss xp played nqc nwv (te rcxf).

Cxd vrda pzw kr continue rx ldeepov vbtq oprargm jz er ienerf jr sc bdx pk, yg riknabeg nmycolom uapk rpats rjen function a cng gtynir rv leoevdp nc interface wbteene diff eertn tscsonie lk tkgg oprmrag. Xuaeesc jr’a vzcd re kxzf kcart el rob voalerl structure jn wvf-velle sealdit, zuah ca dndiga metsi re list a tk kgnmai vcpt rrus vacse kkgz heret tsunnel, s greal ctrq vl heth interface c wfjf ftneo altein inghid eloufsrpuus ildeats tx aknimg siostenc lx thqv goarrmp ereais xr kwet yrjw.

Get Hello! Python
add to cart
sitemap
×

Unable to load book!

The book could not be loaded.

(try again in a couple of minutes)

manning.com homepage