1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width"> 6 <title>The Room Adventure: Additional Features</title> 7 8 <link href="/index.css" rel="stylesheet" type="text/css"/> 9 <link href="/roomadventure/rooms.css" rel="stylesheet" type="text/css"/> 10 <link rel="shortcut icon" href="http://stephenjwolf.com/coding/favicon.ico" type="image/x-icon"/> 11 </head> 12 <body> 13 <div id="body"><!-- Required div for navigation bar --> 14 <div class="imgfloater max150px"><img src="/images/SergeiStudious.png"></div> 15 <h1>The Room Adventure: Additional Features</h1> 16 17 <h2>Offering passcode hints</h2> 18 <h4>Difficulty: ★★☆☆☆</h4> 19 <h4><em>Requirement: Passcode Ending</em></h4> 20 21 <div class="flex-container"> 22 <div> 23 <!--Explanation--> 24 <p>In the passcode ending, the player is shown their inventory on a popup and then it disappears before they enter 25 the passcode. Remembering nine numbers in the right order can be a challenge. Scientifically speaking, we 26 naturally can only remember seven digits in a short-term situation like that. That's why base phone numbers are 27 seven digits long.</p> 28 29 <p>Let's give the player some help and show the password clues on the screen that asks for the password. Let's 30 also let the player ask for a hint that clues them in as to how they're supposed to arrange the numbers. 31 32 <h2>What we need to do</h2> 33 <ul> 34 <li>Update the passcode alert to include the pieces of the passcode.</li> 35 <li>Add a 'help' option to the passcode entry.</li> 36 <li>Pick a hint from a list (or only have one).</li> 37 <li>Charge some points for the hint (optional).</li> 38 </ul> 39 </div> 40 <div class="imgwrapper"> 41 <br> 42 <!--Screenshot--> 43 <img src="/roomadventure/screenimages/textpasscodehint02.png"></div> 44 </div> 45 46 47 <h2>Step 1</h2> 48 <p>Right now inside of <span class="function">moveToRoom</span>, we do a quick job of asking for the passcode.</p> 49 50 <div class="code"> 51 <ul> 52 53 <li><span class="keyword">else if</span> (direction === <span class="string">"exit"</span>)</li> 54 <li>{ 55 <ul> 56 <li><span class="keyword">var</span> guessPasscode = <span class="function">prompt</span>(<span 57 class="string">"What's the passcode?"</span>); 58 </li> 59 <li><span class="keyword">if</span> (guessPasscode === <span class="object">passcode</span>.<span 60 class="property">exitCode</span>) 61 </li> 62 </ul> 63 </li> 64 <li><span class="comment">//rest of function</span></li> 65 </ul> 66 </div> 67 68 <p>When we created this, we kept it simple. But now that we're going to get more complex, let's create a new function 69 to deal with our new update.</p> 70 71 <p>Let's create a function call here since we're already looking at this code. Inside <span 72 class="function">moveToRoom</span>, change the <span class="keyword">var</span> line to this.</p> 73 74 <div class="code"> 75 <ul> 76 <li> 77 <ul> 78 <li><span class="keyword">var</span> guessPasscode = <span class="function">getPasscodeGuess</span>();</li> 79 </ul> 80 </li> 81 </ul> 82 </div> 83 84 <h2>Step 2</h2> 85 <p>Let's get oriented before we create our function. It's important to remember what we already have in place and what 86 we need to change.</p> 87 88 <p>There are a couple things the new function needs to do. We want it to show the passcode pieces the player has and 89 we want to allow the player to guess a hint or the passcode. If we put this in <span 90 class="function">moveToRoom</span>, it would really clutter up that function. We always want functions to be as 91 small and as focused as possible.</p> 92 93 <p><strong>Remember: to create a new function, you want to be outside of any other functions. Find a place between two 94 functions so you're not inside another function's set of braces.</strong></p> 95 96 <p>We're going to loop through the <span class="object">player</span>'s <span class="property">inventory</span> to 97 find the passcode pieces the player picked up. When we originally created the <span class="object">passcode</span> 98 object, we made a <span class="property">codes</span> property. We can use that to identify our passcode pieces, 99 like we look for inventory items to fix things.</p> 100 101 <p>We have this line in <span class="function">getPasscode</span>. </p> 102 103 104 <h2>Step 3</h2> 105 <p>Let's start creating the function. We're going to build a text string to hold the passcode pieces. We will then 106 loop through the player's inventory to see if they have any pieces. Ready? This kind of code should look 107 familiar.</p> 108 109 <div class="code"> 110 <ul> 111 <li><span class="keyword">function</span> <span class="function">getPasscodeGuess</span>()</li> 112 <li>{ 113 <ul> 114 <li><span class="keyword">var</span> passcodePieces = <span class="string">""</span>;</li> 115 <li><span class="keyword">for</span> (<span class="keyword">var</span> i = 0; i < <span 116 class="object">player</span>.<span 117 class="property">inventory</span>.<span class="property">length</span>; i++) 118 </li> 119 <li>{ 120 <ul> 121 <li><span class="comment">//let's create a helper variable</span></li> 122 <li><span class="keyword">var</span> item = <span class="object">player</span>.<span 123 class="property">inventory</span>[i]; 124 </li> 125 <li> </li> 126 <li><span class="keyword">if</span> (<span class="object">passcode</span>.<span 127 class="property">codes</span>.<span class="function">indexOf</span>(item) !== -1) 128 </li> 129 <li>{ 130 <ul> 131 <li>passcodePieces += item + <span class="string">" "</span>;</li> 132 </ul> 133 </li> 134 <li>}</li> 135 </ul> 136 </li> 137 <li>}</li> 138 </ul> 139 </li> 140 <li> </li> 141 <li><span class="comment">//there's more of this function to come shortly...</span></li> 142 </ul> 143 </div> 144 145 146 <h2>Step 4</h2> 147 148 <div class="flex2"> 149 150 151 <div> 152 <p>If the player hasn't found any passcode pieces, let's say so. Otherwise, we'll show the passcode pieces. Let's 153 add this.</p> 154 155 <div class="code"> 156 <ul> 157 <li> 158 <ul> 159 <li><span class="keyword">var</span> text = <span class="string">""</span>;</li> 160 <li><span class="keyword">if</span> (passcodePieces === <span class="string">""</span>)</li> 161 <li>{ 162 <ul> 163 <li>text += <span class="string">"You haven't found any passcode pieces yet. "</span>;</li> 164 </ul> 165 </li> 166 <li>}</li> 167 <li><span class="keyword">else</span></li> 168 <li>{ 169 <ul> 170 <li>text += <span class="string">"Passcode pieces you have found: "</span>;</li> 171 <li>text += passcodePieces;</li> 172 </ul> 173 </li> 174 <li>}</li> 175 </ul> 176 </li> 177 <li> </li> 178 <li><span class="comment">//there's more of this function to come shortly...</span></li> 179 </ul> 180 </div> 181 182 </div> 183 <div class="max150px"> 184 <figure><img src="/roomadventure/screenimages/textpasscodehint01.png" alt="No passcode pieces"> 185 <figcaption>No passcode pieces</figcaption> 186 </figure> 187 </div> 188 189 </div> 190 191 <h2>Step 5</h2> 192 <p>Let's finish building the text string we're going to display. I'm adding a small cost for the hint, but you don't 193 have to. We'll add the value when we update the <span class="function">getPasscode</span> function, but we'll set up 194 some of the code to handle it as we go.</p> 195 196 <div class="code"> 197 <ul> 198 <li> 199 <ul> 200 <li>text += <span class="string">"You can type 'hint' if you need one. "</span>;</li> 201 <li><span class="keyword">if</span> (<span class="object">passcode</span>.<span 202 class="property">hintCost</span>) 203 </li> 204 <li>{ 205 <ul> 206 <li> 207 <li>text += <span class="string">"Taking a hint costs " + <span class="object">passcode</span>.<span 208 class="property">hintCost</span> + " points. "</span>; 209 </li> 210 </ul> 211 </li> 212 <li>}</li> 213 <li>text += <span class="string">"Type in the passcode below. "</span>;</li> 214 </ul> 215 </li> 216 <li> </li> 217 <li><span class="comment">//there's more of this function to come shortly...</span></li> 218 </ul> 219 </div> 220 221 <h2>Step 6</h2> 222 <p>Now we need to ask the player to either enter a passcode or ask for a hint. But if the player does ask for a hint, 223 then we need to show one and then let them try to enter the passcode again. Does this sound familiar? We needed to 224 do something similar when we created the <span class="function">getDirection</span> function.</p> 225 226 <p>We're going to need a <span class="keyword">while</span> loop. It's going to keep looping until the player types in 227 something other than <span class="string">hint</span>. As with most programming, we have a couple of different 228 options for handling this. We could use a <span class="keyword">do...while</span> loop, or we could use a <span 229 class="keyword">while</span>(<span class="keyword">true</span>) loop. </p> 230 231 <p>Even though I usually avoid them, the <span class="keyword">while</span>(<span class="keyword">true</span>) saves 232 us a little code here.</p> 233 234 <p>We're going to use a <em>not</em> check here because the function will immediately end if the player did not type 235 <span class="string">hint</span>. We could use an <span class="keyword">else</span> statement after that, but we 236 won't actually need one, because the only reason the loop and function would continue is because the player did type 237 in <span class="string">hint</span>. If you want the <span class="keyword">else</span> in there, you'll just wrap 238 the hint-related code in one. </p> 239 240 241 <div class="code"> 242 <ul> 243 <li> 244 <ul> 245 <li><span class="keyword">while</span>(<span class="keyword">true</span>)</li> 246 <li>{ 247 <ul> 248 <li><span class="keyword">var</span> guess = <span class="function">prompt</span>(text);</li> 249 <li><span class="keyword">if</span> (guess !== <span class="string">"hint"</span>)</li> 250 <li>{ 251 <ul> 252 <li><span class="keyword">return</span> guess;</li> 253 </ul> 254 </li> 255 <li>}</li> 256 </ul> 257 </li> 258 </ul> 259 </li> 260 <li> </li> 261 <li><span class="comment">//there's more of this function to come shortly...</span></li> 262 </ul> 263 </div> 264 265 <p>That's the quick check for the word <span class="string">hint</span>.</p> 266 267 <p>But what if they player uses a capital letter somewhere? We controlled for this before in <span class="function">getDirection</span>. 268 We used the <span class="function">toLowerCase</span> method on the direction the player typed in so we could simply 269 how we checked things. We should probably do that here too.</p> 270 271 <p>But also, do you remember what we did when the player typed in <span class="string">exit</span>? We were super 272 cautious and allowed them to put the word anywhere in the string. We used <span class="function">indexOf</span> to 273 see if <span class="string">exit</span> had been used anywhere in the text.</p> 274 275 <p>In the interest of expanding your coding skills, let's put these two together and really try to work with the 276 player's intentions. You could replace the <span class="keyword">if</span> statement above with this to allow more 277 flexibility for the player.</p> 278 279 <div class="code"> 280 <ul> 281 <li> 282 <ul> 283 <li> 284 <ul> 285 <li><span class="keyword">if</span> (guess.<span class="function">toLowerCase</span>().<span 286 class="function">indexOf</span>(<span class="string">"hint"</span>) === -1) 287 </li> 288 </ul> 289 </li> 290 </ul> 291 </li> 292 </ul> 293 </div> 294 295 <p>Remember that if <span class="function">indexOf</span> sends back a <code>-1</code>, then the string wasn't found. 296 So as long as your passcode doesn't actually have the word <span class="string">hint</span> in it, then this will 297 work well.</p> 298 299 300 <h2>Step 7</h2> 301 <p>If the function is still running, then we want to give a hint. If you're charging the player some points for the 302 hint, then we have to take care of that first.</p> 303 <p>Only include this part if you want the player to give up some points for each hint.</p> 304 305 <div class="code"> 306 <ul> 307 <li> 308 <ul> 309 <li> 310 <ul> 311 <li><span class="keyword">if</span> (<span class="object">player</span>.<span 312 class="property">score</span> < <span class="object">passcode</span>.<span 313 class="property">hintCost</span>) 314 </li> 315 <li>{ 316 <ul> 317 <li><span class="function">alert</span>(<span class="string">"Sorry, you need at least "</span> + 318 <span class="object">passcode</span>.<span class="property">hintCost</span> + <span class="string">" 319 points to buy a hint."</span>); 320 </li> 321 <li><span class="keyword">continue</span>;</li> 322 </ul> 323 </li> 324 <li>}</li> 325 <li> </li> 326 <li><span class="object">player</span>.<span class="property">score</span> -= <span class="object">passcode</span>.<span 327 class="property">hintCost</span>; 328 </li> 329 </ul> 330 </li> 331 </ul> 332 </li> 333 <li> </li> 334 <li><span class="comment">//there's more of this function to come shortly...</span></li> 335 </ul> 336 </div> 337 338 <p>This is a quick check to see if the player has enough points to spend. If not, the loop <span class="keyword">continue</span>s. 339 Remember, this means the computer jumps back to the top of the loop and runs it again without running any code below 340 this point. So, if there <em>are</em> enough points, we deduct them from the player. I don't want to give an extra 341 popup for this, so I'm going to include this information with the hint. But if you want to add a separate <span 342 class="function">alert</span> here, you certainly can.</p> 343 344 <h2>Step 8</h2> 345 <p>If we've gotten to this point in the function, then it's actually time to give a hint. You have a choice between 346 giving a single hint or having a few.</p> 347 348 <h3>Offering a single hint</h3> 349 <p>If you only want to have one hint to offer, then you could do something like this. I still made it sort of a puzzle 350 for the player, but you can be more direct if you want.</p> 351 352 <div class="code"> 353 <ul> 354 <li> 355 <ul> 356 <li> 357 <ul> 358 <li><span class="keyword">var</span> hint = <span class="string">"In Kindergarten, you learned a song that 359 sounds like <em>Twinkle, Twinkle, Little Star"</em>"</span>; 360 </li> 361 <li>hint += <span class="string">" but it's about something being in a specific order."</span>; 362 </li> 363 <li>hint += <span class="string">" Your clues have code words that should be put in that same 364 order."</span>); 365 </li> 366 367 <li><span class="keyword">if</span> (<span class="object">passcode</span>.<span 368 class="property">hintCost</span>) 369 </li> 370 <li>{ 371 <ul> 372 <li> 373 <li>hint += <span class="string">" (This clue cost you " + <span class="object">passcode</span>.<span 374 class="property">hintCost</span> + " points.)"</span>; 375 </li> 376 </ul> 377 </li> 378 <li>}</li> 379 380 <li><span class="function">alert</span>(hint);</li> 381 </ul> 382 </li> 383 <li>} <span class="comment">//this closes the <em>while</em> loop</span></li> 384 </ul> 385 </li> 386 <li>} <span class="comment">//this closes the function</span></li> 387 </ul> 388 </div> 389 390 <p>That does it for the single hint. You're all done with this feature.</p> 391 392 393 <h3>Offering several hints</h3> 394 395 396 <p>In the interest of expanding your coding knowledge and practice, let's create multiple hints. I'm going to create a 397 set of hints in an array and then randomly pick a hint each time the player asks for one. This means the player 398 could be unlucky and get the same hint more than once (unless we control for that) but I think that makes it more 399 interesting.</p> 400 401 <h4>Leaving an unfinished function</h4> 402 <p>We're going to jump out of the <span class="function">getPasscodeGuess</span> function for a few minutes. You might 403 get some errors showing up, but we'll fix them.</p> 404 405 406 <h4>Updating the <span class="function">getPasscode</span> function</h4> 407 <p>At the top of the function, we recreate the <span class="object">passcode</span> object. Now, ever though we can 408 create new properties on the fly by just assigning them, it's better practice to show that we intend to do so if we 409 can.</p> 410 411 <p>For good code readability, let's add a <span class="property">hints</span> property to the <span class="object">passcode</span> 412 object. Well also add the cost of the hint here, which you can set to <code>0</code> if you don't want a cost.</p> 413 414 <div class="code"> 415 <ul> 416 <li>passcode =</li> 417 <li>{ 418 <ul> 419 <li><span class="property">reward</span>: 100,</li> 420 <li><span class="property">penalty</span>: 25,</li> 421 <li><span class="property">exitCode</span>: <span class="string">""</span>,</li> 422 <li><span class="property">codes</span>: [],</li> 423 <li><span class="property">rooms</span>: []<strong>, <span class="comment">//remember the comma 424 here</span></strong></li> 425 <li><strong><span class="property">hints</span>: [], <span class="comment"> //add this</span> </strong> 426 </li> 427 <li><strong><span class="property">hintCost</span>: 5</strong></li> 428 </ul> 429 </li> 430 <li>};</li> 431 </ul> 432 </div> 433 434 <p>When we make the clues for the player and the passcode, let's also call for the hints to be created.</p> 435 <p>To make it easy to find where to put this, go to the very bottom of the <span class="function">getPasscode</span> 436 function.</p> 437 438 <div class="code"> 439 <ul> 440 <li> 441 <ul> 442 <li>passcode.hints = <span class="function">makePasscodeHints</span>(passcode); <span 443 class="comment">//new</span> 444 </li> 445 <li><span class="keyword">return</span>; <span class="comment">//already there</span></li> 446 </ul> 447 </li> 448 <li>} <span class="comment">//already there</span></li> 449 </ul> 450 </div> 451 452 <h4>Creating the <span class="function">makePasscodeHints</span> function</h4> 453 <p>We made a global set of hints. Now we'll copy that set so we can use it without making changes to the original 454 set.</p> 455 456 <div class="code"> 457 <ul> 458 <li><span class="keyword">function</span> <span class="function">getPasscodeHints</span>(passcode)</li> 459 <li>{ 460 <ul> 461 <li><span class="keyword">var</span> hints = [];</li> 462 <li>hints.<span class="function">push</span>(<span class="string">"Twinkle, Twinkle, Little Star sounds like 463 another song you learned in Kindergarten that reminds us of a certain order."</span>); 464 </li> 465 <li>hints.<span class="function">push</span>(<span class="string">"A group of animals had a race. The aardvark 466 finished first. The bunny was second. The cat was a purrfect third. The dog defended fourth. The elephant 467 was fifth."</span>); 468 </li> 469 <li>hints.<span class="function">push</span>(<span class="string">"Two friends were at the zoo. Rodger went 470 and FED the horses, but he did it wrong. Instead, his buddy STU did it right."</span>); 471 </li> 472 <li> </li> 473 <li><span class="comment">//How about some really helpful hints?</span></li> 474 475 <li><span class="keyword">var</span> exitCode = <span class="object">passcode</span>.<span 476 class="property">exitCode</span>; 477 </li> 478 479 <li><span class="keyword">for</span> (<span class="keyword">var</span> i = 0; i < exitCode.<span 480 class="property">length</span>; i += 3) 481 </li> 482 <li>{ 483 <ul> 484 <li><span class="keyword">var</span> index = <span class="object">Math</span>.<span 485 class="function">floor</span>(<span 486 class="object">Math</span>.<span class="function">random</span>() * exitCode.<span 487 class="property">length</span>); 488 </li> 489 <li>hints.<span class="function">push</span>(<span class="string">"Passcode digit #"</span> + (index + 1) 490 + <span class="string">" is "</span> + exitCode.<span 491 class="function">substring</span>(index, 1)); 492 </li> 493 </ul> 494 </li> 495 <li>}</li> 496 <li><span class="keyword">return</span> hints;</li> 497 </ul> 498 </li> 499 <li>}</li> 500 </ul> 501 </div> 502 503 <h4>Finishing the <span class="function">getPasscodeGuess</span> function</h4> 504 <div class="flex2"> 505 <div> 506 <p>We left this function unfinished which is probably showing you some errors. Let's wrap it up finally.</p> 507 <p>We have everything we need now, so we just need to pick a hint to show.</p> 508 <p>This goes at the bottom of the <span class="function">getPasscodeGuess</span> function we were creating.</p> 509 510 <div class="code"> 511 <ul> 512 <li> 513 <ul> 514 <li> 515 <ul> 516 <li><span class="comment">//make a copy of the global hints so we don't alter them accidentally</span> 517 </li> 518 <li><span class="keyword">var</span> hints = <span class="object">passcode</span>.<span 519 class="property">hints</span>.<span 520 class="function">slice</span>(); 521 </li> 522 <li> </li> 523 <li><span class="comment">//now let's pick a hint</span></li> 524 <li><span class="keyword">var</span> hintNumber = <span class="object">Math</span>.<span 525 class="function">floor</span>(<span 526 class="object">Math</span>.<span class="function">random</span>() * hints.<span class="property">length</span>); 527 </li> 528 <li><span class="keyword">var</span> hint = <span class="string">"Hint #"</span> + (hintNumber + 1) + 529 <span 530 class="string">" of "</span> + hints.<span class="property">length</span> + <span 531 class="string">": "</span>; 532 </li> 533 <li>hint += hints[hintNumber];</li> 534 535 536 <li><span class="keyword">if</span> (<span class="object">passcode</span>.<span 537 class="property">hintCost</span>) 538 </li> 539 <li>{ 540 <ul> 541 <li> 542 <li>hint += <span class="string">" (This clue cost you " + <span 543 class="object">passcode</span>.<span 544 class="property">hintCost</span> + " points.)"</span>; 545 </li> 546 </ul> 547 </li> 548 <li>}</li> 549 550 <li><span class="function">alert</span>(hint);</li> 551 <li> </li> 552 <li><span class="comment">//if you want to remove the hint from the list, add this</span></li> 553 <li><span class="comment">//note: the list of hints will be reset if the player guesses wrong and 554 tries again</span> 555 </li> 556 <li>hints.<span class="function">splice</span>(hintNumber, 1);</li> 557 </ul> 558 </li> 559 <li> </li> 560 <li>} <span class="comment">//this closes the <em>while</em> loop</span></li> 561 </ul> 562 </li> 563 <li>} <span class="comment">//this closes the function</span></li> 564 </ul> 565 </div> 566 567 <p>That was a lot of pieces to add multiple hints, but it will enrich the game even more, especially if you get 568 creative with your hints or change the format of the game.</p> 569 </div> 570 <div class="max150px"> 571 <figure><img src="/roomadventure/screenimages/textpasscodehint03.png" alt="Multiple hints option"> 572 <figcaption>Multiple hints option</figcaption> 573 </figure> 574 </div> 575 </div> 576 577 <h2>Here's a hint... Keep coding!</h2> 578 <h2>—Dr. Wolf</h2> 579 580 <div id="prevnext"></div> 581 <!-- required section for navigation sidebar --></div> 582 <script src="/navigator.js"></script> 583 <script>begin("roomadventure");</script> 584 <!-- end of required section for navigation sidebar --> 585 </body> 586 </html> 587