addkeycheck.html
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>Checking that the Played Can Unlock the Locks</h2> 
18     <h4>Difficulty: &#9733;&#9733;&#9733;&#9734;&#9734;</h4> 
19     <h4><em>Requirement: Lock and Key Feature</em></h4> 
20    
21     <div class="flex-container"> 
22       <div> 
23         <!--Explanation--> 
24         <p>We installed a locked door feature in <a href="addlockedroom.html">Add Locked Rooms</a>. This requires you, as 
25           the developer, to place keys in the rooms and to lock doors. This must be done so you don't have a key hidden 
26           behind a locked door you need it for.</p> 
27    
28         <p>Even with good planning, mistakes can happen. You put the brass key in the office to unlock the dining room. 
29           You put the silver key in the dining room to unlock the hallway. Sounds good, except, you have to pass through 
30           the hallway to get to the office, so you can never get to the brass key, therefore you can never get to the 
31           silver key, and you can never unlock the hallway, which would let you get the brass key. (Follow all that?)</p> 
32    
33         <p>In addition, if you use certain randomization features, this whole process becomes a real mess.</p> 
34    
35         <p>We need a way to check to make sure the lock and key setup will allow the player to complete the game. Even if 
36           you set up the locks and keys yourself, you should create this and at least run it from the console to make sure 
37           your game is playable.</p> 
38    
39         <h2>What we need to do</h2> 
40    
41         <ul> 
42           <li>Create a set of tracking variables so we don't change actual room or player information.</li> 
43           <li>Make a list of locked rooms and all keys from the room set we are testing.</li> 
44           <li>Take keys from any room we are in and try to unlock any doors we can.</li> 
45           <li>Randomly move to any possible, unlocked exit.</li> 
46           <li>Continue until all locked doors are unlocked or we run out of tests.</li> 
47         </ul> 
48       </div> 
49    
50       <div class="imgwrapper"> 
51         <br> 
52         <!--Screenshot--> 
53         <img src="/roomadventure/screenimages/checkkeys01.png"> 
54       </div> 
55     </div> 
56    
57     <h2>Using console.log to debug</h2> 
58     <p>This function has a few tricky details. It can be hard to keep track of it all because we can't see what's 
59       happening.</p> 
60    
61     <p>For situations like this, I make heavy use of <code><span class="object">console</span>.<span 
62         class="function">log</span>()</code>. I put variables names ini there and then check the console when I run the 
63       function so I can check to see what's happening. It helps me figure out if something goes wrong.</p> 
64    
65     <p>In the code here, you will see a lot of <span class="object">console</span> commands. You do not have to type these 
66       in if you don't want to. They won't change how your code runs at all. They're just there so you can see some output 
67       in the console.</p> 
68    
69     <p>You can see the output in the <code>repl.it</code> console window or by accessing developer tools, which you can 
70       usually find by pressing <kbd class="key">f12</kbd> on your keyboard.</p> 
71    
72     <h2>Step 1: Initializing our variables</h2> 
73     <p>We only want this function to test the locks and keys. We don't want it to actually unlock anything or really move 
74       the player around. So we need to set up a few variables that will hold some information for us.</p> 
75    
76     <div class="code"> 
77       <ul> 
78         <li><span class="keyword">function</span> <span class="function">checkKeys</span>(availableRooms, playerStart, 
79           allowRandomStart) 
80         </li> 
81         <li>{ 
82           <ul> 
83             <li><span class="comment">//we don't want to alter the rooms, so we're making new variables</span></li> 
84             <li><span class="object">availableRooms</span> = <span class="object">availableRooms</span> || <span 
85                 class="object">rooms</span>; 
86             </li> 
87             <li><span class="object">playerStart</span> = playerStart || <span class="object">player</span>.<span 
88                 class="property">currentRoom</span>.<span class="property">.name</span>; 
89             </li> 
90             <li><span class="object">player</span>.<span class="property">_tempkeys</span> = <span 
91                 class="object">player</span>.<span class="property">_tempkeys</span> || []; 
92             </li> 
93             <li>&nbsp;</li> 
94             <li><span class="keyword">var</span> foundKeys = <span class="object">player</span>.<span class="property">_tempkeys</span>.<span 
95                 class="function">slice</span>(); 
96             </li> 
97             <li><span class="keyword">var</span> numberRooms = 0;</li> 
98             <li><span class="keyword">var</span> lockedRooms = [];</li> 
99             <li><span class="keyword">var</span> startRooms = [];</li> 
100          </ul> 
101        </li> 
102      </ul> 
103    </div> 
104   
105    <h3>Code breakdown</h3> 
106    <p><a href="#step2">Or skip directly to the next step.</a></p> 
107   
108    <h4>The parameters</h4> 
109    <p>We are taking in three parameters here. One is a set of <code>availableRooms</code> you want to test out. This 
110      could be the global set of rooms, or it could be a smaller set of them, like one floor of the house, or an area of a 
111      forest. We are going to put in a failsafe so that if you leave out this parameter, the function will default to 
112      using the global <span class="object">rooms</span> object.</p> 
113   
114    <p>The <code>playerStart</code> is where you want the player to start in the house. This could make a huge difference 
115      to the game, depending on locks and keys! If you have a specific setup in mind, you need to control this carefully. 
116    </p> 
117   
118    <p>Like the rooms, we're going to have a backup plan if you don't send in the starting point for the player. In that 
119      case, we will use the player's current room.</p> 
120   
121    <p>We are also using an <code>allowRandomStart</code> switch. If the <code>playerStart</code> location is not a valid 
122      room, we can either say the setup doesn't work, or we could randomly pick a room for the player to start in and test 
123      that.</p> 
124   
125    <p>Leaving this out when you call the function would make it default to <span class="keyword">undefined</span>, which 
126      would be treated as <span class="keyword">false</span> when we test for it, therefore not allowing the starting 
127      point to be randomized.</p> 
128   
129    <p>If we pass in <span class="keyword">true</span> for this, then it may help you figure out a good starting room if 
130      you're using the console to show values.</p> 
131   
132    <p>It is generally better to control your parameters directly by sending in specific arguments when you write your 
133      code. I like to have failsafes in place. By the way, if you don't send in a set of rooms, then you <em>can't</em> 
134      send in a player's starting place or the lock-in-place flag. Arguments and parameters have to line up when you send 
135      them in and when you assign them in the function.</p> 
136   
137    <h4>Using the OR <code>||</code> operator for assignment</h4> 
138    <p>We usually use OR when we do a conditional test, like in an <span class="keyword">if</span> or <span 
139        class="keyword">while</span> statement. But JavaScript lets us use it when we assign values too.</p> 
140   
141    <p>Go the the equals sign and then start at the first value. If that translates to <span class="keyword">true</span>, 
142      then it gets assigned to the variable. So if we send in a set of available rooms, then that's what we'll use. But if 
143      we didn't send in a set, leaving it <span class="keyword">undefined</span>, that would be a <span class="keyword">false</span> 
144      statement. The OR <code>||</code> operator then moves on to the next variable. If it's the last one in the set, it 
145      assigns it, whatever its value. In this case, the global <span class="object">rooms</span> object.</p> 
146   
147    <p>If you have several OR operators in a row, it would keep moving down the list until either one of them was <span 
148        class="keyword">true</span> or until it reaches the last one.</p> 
149   
150    <h4>The underscore</h4> 
151    <p>We usually avoid using the underscore when we name things. By convention, it is used for <em>private</em> 
152      variables, or variables that really should not be touched by another programmer. It's not a rule and there's nothing 
153      stopping them from messing with it. But it's asking them not to.</p> 
154   
155    <p>We're using it to control a temporary set of keys that we need to keep track of while we check the 
156      locked-room-and-key layout. We are attaching it to the global <span class="object">player</span> object so it can be 
157      used again if needed. Why? Well, if you are using the floor/area separator, you may need to know what keys the 
158      player has before coming into an area when you're testing things out. And we don't want to change the player's 
159      actual key inventory.</p> 
160   
161    <h4>Copying an array</h4> 
162    <p>When we need a shallow copy of an array (like copying strings and numbers), we need to use the <span 
163        class="function">slice</span> method. This leaves the original array intact and sends back a new copy of it. <span 
164        class="function">slice</span> can also return just sections of an array, but here we need the whole copy.</p> 
165   
166    <p>We can't just assign the array as equal without the <span class="function">slice</span>. If we did, then the new 
167      array would just be a <em>pointer</em> to the original array. So changing one would change "both." It's not really 
168      "both" because there's only one array with two names, like having a nickname. So, to make an array copy, we need 
169      <span 
170          class="function">slice</span>.</p> 
171   
172   
173    <h2 id="step2">Step 2: Make a list of locks and keys</h2> 
174    <p>Let's loop through the list of available rooms. We'll count the rooms we have, and make lists of the rooms that are 
175      locked, and all the keys that can be found.</p> 
176   
177    <p>You've seen code like this before.</p> 
178   
179    <div class="code"> 
180      <ul> 
181        <li> 
182          <ul> 
183            <li><span class="keyword">for</span> (<span class="keyword">var</span> roomName <span 
184                class="keyword">in</span> <span class="object">availableRooms</span>) 
185            </li> 
186            <li>{ 
187              <ul> 
188                <li>numberRooms++;</li> 
189                <li><span class="keyword">var</span> <span class="object">room</span> = <span 
190                    class="object">availableRooms</span>[roomName]; 
191                </li> 
192                <li>startRooms.<span class="function">push</span>(roomName);</li> 
193                <li>&nbsp;</li> 
194                <li><span class="keyword">if</span> (<span class="object">room</span>.<span class="property">locked</span> 
195                  && <span class="object">room</span>.<span class="property">locked</span>.<span 
196                      class="property">length</span> > 0) 
197                </li> 
198                <li>{ 
199                  <ul> 
200                    <li>lockedRooms.<span class="function">push</span>(roomName);</li> 
201                  </ul> 
202                </li> 
203                <li>}</li> 
204                <li>&nbsp;</li> 
205                <li><span class="keyword">if</span> (<span class="object">room</span>.<span class="property">keys</span> 
206                  && <span class="object">room</span>.<span class="property">keys</span>.<span 
207                      class="property">length</span> > 0) 
208                </li> 
209                <li>{ 
210                  <ul> 
211                    <li>foundKeys = foundKeys.<span class="function">concat</span>(<span class="object">room</span>.<span 
212                        class="property">keys</span>); 
213                    </li> 
214                  </ul> 
215                </li> 
216                <li>}</li> 
217              </ul> 
218            </li> 
219            <li>}</li> 
220          </ul> 
221        </li> 
222      </ul> 
223    </div> 
224   
225    <h3>Code breakdown</h3> 
226    <p><a href="#step3">Or skip directly to the next step.</a></p> 
227   
228    <h4>Counting and listing the rooms</h4> 
229    <p>We're keeping track of the number of rooms to help us figure out how many tries we should have to see if the keys 
230      and locks work. It's probably not that necessary, but why not?</p> 
231   
232    <p>We're keeping a list of <code>startRooms</code> in case there isn't a valid starting room for the player. This will 
233      then be the list of rooms we could pick from to try out.</p> 
234   
235   
236    <h4>Concatenating arrays</h4> 
237    <p>Concatenation just means that we add things together, like when we add strings. Concatenation takes two (or more) 
238      arrays and puts them all together into one bigger array, like copying both onto a new sheet.</p> 
239   
240    <p>The thing to remember, and it's easy to forget, is that this does not change the original arrays. Instead, it sends 
241      back a <em>new</em> array. That means you have to save it to a variable if you want to use it, and what's the point 
242      of making it if you don't want to use it?</p> 
243   
244    <p>We're overwriting the <code>foundKeys</code> array here. In essence, it adds the second array to the end of the 
245      first one instead of creating a new array. Well, that's just what looks like is happening.</p> 
246   
247    <h4>Testing object properties safely</h4> 
248    <p>You'll use lines like this a lot when you need to test certain properties of objects.</p> 
249   
250    <div class="code"> 
251      <ul> 
252        <li><span class="keyword">if</span> (<span class="object">room</span>.<span class="property">locked</span> && 
253          <span 
254              class="object">room</span>.<span class="property">locked</span>.<span class="property">length</span> > 0) 
255        </li> 
256      </ul> 
257    </div> 
258   
259    <p>When you decided to add locks to your rooms, did you add a <span class="property">locked</span> property to every 
260      single room, or just the ones you locked? We oly added them to the ones we locked, so most of your rooms won't even 
261      have this property at all. That means it's <span class="keyword">undefined</span>. By itself, that's no big deal. 
262    </p> 
263   
264    <p>But the <span class="property">locked</span> property is an array (when it's there). All arrays, even empty ones, 
265      test as <span class="keyword">true</span>, so we can only tell if the room is locked by seeing if there is at least 
266      on key in the <span class="property">locked</span> list.</p> 
267   
268    <p>So we need the <span class="property">length</span> property of the room's <span class="property">locked</span> 
269      array. Buuuut. If the room doesn't even <em>have</em> a <span class="property">locked</span> property, then we would 
270      cause an error when we try to get its <span class="property">length</span>.</p> 
271   
272    <p>Ugh, right? So, we first need to make sure that the object <em>has the property we are looking for before we can 
273      check to see if that list has anything in it.</em></p> 
274   
275    <p>We use the AND <code>&&</code> operator for this and it has to be set up in this order. We test for the <span 
276        class="property">locked</span> property first to see if it even exists. If it doesn't, the JavaScript doesn't even 
277      look at the next part because the AND operator needs everything to be <span class="keyword">true</span>, so if the 
278      first part isn't <span class="keyword">true</span> then the whole thing can't be <span class="keyword">true</span> 
279      either. This allows us to prevent an error.</p> 
280    <p>At times, we take it one step further and start by testing if there even is an object! Like this.</p> 
281   
282    <div class="code"> 
283      <ul> 
284        <li><span class="keyword">if</span> (<span class="object">room</span> && <span class="object">room</span>.<span 
285            class="property">locked</span> && <span class="object">room</span>.<span class="property">locked</span>.<span 
286            class="property">length</span> > 0) 
287        </li> 
288      </ul> 
289    </div> 
290   
291    <h2 id="step3">Step 3: Printing to the console</h2> 
292    <p>Optional: <a href="#step5">Or skip directly to the next step.</a></p> 
293   
294    <p>Let's print our first set of variables to the console so we can check them when we run them. This can help us to 
295      troubleshoot any problems later when we run the function.</p> 
296   
297    <div class="code"> 
298      <ul> 
299        <li> 
300          <ul> 
301            <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"***Start of 
302              check"</span>); 
303            </li> 
304            <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"#rooms: 
305              "</span> + numberRooms); 
306            </li> 
307            <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"locked: 
308              "</span> + lockedRooms); 
309            </li> 
310            <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"keys: "</span> 
311              + foundKeys); 
312            </li> 
313          </ul> 
314        </li> 
315      </ul> 
316    </div> 
317   
318    <p>There are many ways to debug a program. You can use breakpoints and step through your code, tracking and watching 
319      variables as you go. Or you can do something like this.</p> 
320   
321    <p>I like this method in the beginning of troubleshooting because it gives a quick overview and I can usually find 
322      things faster. Also, when you have something that loops a lot, if you're stepping through it, it can take a really 
323      long time.</p> 
324   
325    <p>By the way, if you want to send an object to the console, you can, but put it on its one console line. Don't use 
326      the strings like I did. So if you wanted to print the available rooms, you could include this.</p> 
327   
328    <div class="code"> 
329      <ul> 
330        <li> 
331          <ul> 
332            <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"available 
333              rooms: "</span>; 
334            </li> 
335            <li><span class="object">console</span>.<span class="function">log</span>(<span 
336                class="object">availableRooms</span>); 
337            </li> 
338          </ul> 
339        </li> 
340      </ul> 
341    </div> 
342   
343    <p>The reason is that once you have the strings in there, JavaScript converts it to a string using that data type's 
344      <span class="function">toString</span> method. In doing that, an object just gets printed as <span class="string">[object 
345        Object]</span> which isn't useful at all. Doing it the other way allows you to see all the properties and their 
346      values.</p> 
347   
348    <h2 id="step4">Step 4: Reporting back if we have an answer already</h2> 
349    <p>We've barely started the function, we can already test for two situations.</p> 
350   
351    <ol> 
352      <li>If no rooms are locked, then these rooms <em>can</em> be played.</li> 
353      <li>If any rooms are locked but there are no keys, these rooms <em>cannot</em> be played.</li> 
354    </ol> 
355   
356    <p>Let's test for these and if either condition happens let's exit out the function and report back.</p> 
357   
358    <p>Again, the console calls are optional. You can leave them out if you don't want to include them.</p> 
359   
360    <div class="code"> 
361      <ul> 
362        <li> 
363          <ul> 
364            <li><span class="keyword">if</span> (lockedRooms.<span class="property">length</span> === 0)</li> 
365            <li>{ 
366              <ul> 
367                <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"Nothing is 
368                  locked."</span>); 
369                </li> 
370                <li><span class="keyword">return true</span>; <span class="comment">//nothing is locked so sure, 
371                  everything is fine</span></li> 
372              </ul> 
373            <li>} 
374            <li><span class="keyword">else if</span> (foundKeys.<span class="property">length</span> === 0)</li> 
375            <li>{ 
376              <ul> 
377                <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"#foundkeys: 
378                  "</span> + foundKeys.<span class="property">length</span>); 
379                </li> 
380                <li><span class="keyword">return false</span>; <span class="comment">//something is locked but with no 
381                  keys, there's a problem</span></li> 
382              </ul> 
383            </li> 
384            <li>}</li> 
385          </ul> 
386        </li> 
387      </ul> 
388    </div> 
389   
390   
391    <h2 id="step5">Step 5: Was a valid starting position sent in?</h2> 
392   
393    <p>Let's check to make sure the starting room sent in is in the set of rooms we received too. If not, then we have to 
394      do one of two things, and which one depends on that third parameter, <code>allowRandomStart</code>.</p> 
395   
396    <ul> 
397      <li>If the room is invalid and we do allow a random start, then we will pick a random room and try once to solve 
398        this. 
399      </li> 
400      <li>If the room is invalid and we do not allow a random start, then we can't solve this.</li> 
401    </ul> 
402   
403    <div class="code"> 
404      <ul> 
405        <li> 
406          <ul> 
407            <li><span class="keyword">if</span> (!<span class="object">availableRooms</span>[playerStart])</li> 
408            <li>{ 
409              <ul> 
410                <li><span class="keyword">if</span> (allowRandomStart)</li> 
411                <li>{ 
412                  <ul> 
413                    <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"Bad 
414                      room, not picking random: "</span> + playerStart); 
415                    </li> 
416                    <li><span class="keyword">return false</span>;</li> 
417                  </ul> 
418                </li> 
419                <li>}</li> 
420                <li><span class="keyword">else</span> <span class="comment">//pick a random room</span></li> 
421                <li>{ 
422                  <ul> 
423                    <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"Bad 
424                      room, picking random: "</span> + playerStart); 
425                    </li> 
426                    <li><span class="keyword">var</span> index = <span class="object">Math</span>.<span class="function">floor</span>(<span 
427                        class="object">Math</span>.<span class="function">random</span>() * startRooms.<span 
428                        class="property">length</span>); 
429                    </li> 
430                    <li></li> 
431                    playerStart = startRooms[index]; 
432                  </ul> 
433                <li>}</li> 
434              </ul> 
435            </li> 
436            <li>}</li> 
437            <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"start room: 
438              "</span> + playerStart); 
439            </li> 
440          </ul> 
441        </li> 
442      </ul> 
443    </div> 
444   
445   
446    <h2 id="step6">Step 6: Determining the number of steps to take</h2> 
447    <p>We are not using artificial intelligence or a tree search, like a <em>breadth-first search</em> or a <em>depth-first 
448      search</em>, to find out if the keys and locks work. Those would be better and more efficient ways of doing this 
449      process, and if set up correctly, they would always give you the right answer. But they are complicated processes 
450      with recursive functions and so on.</p> 
451   
452    <p>Instead, we're going to use a <em>random walk</em>. The computer is going to randomly pick a valid exit and go in 
453      that direction, pick up a key if there is one, unlock a door if it can.</p> 
454   
455    <p>But for how long should it try? Until everything is unlocked? Well, that's no good if one key is unreachable. So we 
456      need to set a limit on the number of times the computer will try to walk from room to room before giving up. It is 
457      possible that a room is solvable but we might run out of steps before it's figured out.</p> 
458   
459    <p>This calculation is pretty arbitrary. It's not based on anything complex. It's affected by the total number of 
460      rooms and the number of locked rooms. And it's bound between 1000 and 10000 steps. Yes, 10000.</p> 
461   
462    <div class="code"> 
463      <ul> 
464        <li> 
465          <ul> 
466            <li><span class="comment">//How many steps should the player take through the house before we give up?</span> 
467            </li> 
468            <li><span class="keyword">var</span> iterations = numberRooms * lockedRooms.<span 
469                class="property">length</span> * 100; 
470            </li> 
471            <li>iterations = <span class="object">Math</span>.<span class="function">min</span>(<span 
472                class="object">Math</span>.<span class="function">max</span>(iterations, 1000), 10000); 
473            </li> 
474          </ul> 
475        </li> 
476      </ul> 
477    </div> 
478   
479    <p>With my base set of 14 room, two locks and two keys, I ran 100000 iterations to test things out. Yes, one hundred 
480      thousand. I created a helper function to do this and to track the results with a temporary tweak or two to the <span 
481          class="function">checkKeys</span> function to make it work. I had the player randomly placed into any of the 
482      rooms to start and then tested the lock/key placement. At a 100,000 times running the check, it took just over 2.2 
483      seconds. The player took a maximum of 943 steps before determining the room could or could not be solved. On 
484      average, the player took about 97 steps to traverse the house. And randomly placing the player in a room with my 
485      locks and keys where they were created a 78% able-to-play-the-game completion rate. Not bad for our function here. 
486    </p> 
487   
488    <h3>Code breakdown</h3> 
489    <p><a href="#step7">Or skip directly to the next step.</a></p> 
490   
491    <h4>Getting a number within a range</h4> 
492    <p>We start by calculating a number of iterations based on the total number of rooms sent in and the number of rooms 
493      that are locked in that set. You could multiply it by any number you want, but I figured a hundred steps per room 
494      per locked room was plenty.</p> 
495   
496    <p>If you have very few rooms and locks, there many not be enough steps (iterations) to test it all out. On the other 
497      hand, if you have huge numbers, it could take too long or cause a memory issue for the browser.</p> 
498   
499    <p>So we want to contain the values. I picked 1000 to 10000. Again, it's arbitrary and you can change them.</p> 
500   
501    <p>We use a combination of <code><span class="object">Math</span>.<span class="function">min</span></code> and 
502      <code><span class="object">Math</span>.<span class="function">max</span></code> to do this. You use <code><span 
503          class="object">Math</span>.<span class="function">max</span></code> to set the <em>lower</em> boundary. And then 
504      you use <code><span class="object">Math</span>.<span class="function">min</span></code> to set the <em>upper</em>. 
505    </p> 
506   
507    <p>It seems backward. Let's say your calculation produced 200 iterations. If you use <code><span 
508        class="object">Math</span>.<span class="function">min</span>(200, 1000);</code>, then it would pop out 1000. Now 
509      put that with 10000 into <code><span class="object">Math</span>.<span class="function">min</span>(1000, 
510        10000)</code> and you get 1000 iterations, which is our lower limit.</p> 
511   
512    <p>Or, let's say your calculation came up with 3000 iterations. If you use <code><span 
513        class="object">Math</span>.<span class="function">min</span>(3000, 1000);</code>, then it would pop out 3000. Now 
514      put that with 10000 into <code><span class="object">Math</span>.<span class="function">min</span>(3000, 
515        10000)</code> and you get 3000 iterations, which was your number.</p> 
516   
517    <p>Finally, let's say your calculation came up with 60000 iterations. If you use <code><span 
518        class="object">Math</span>.<span class="function">min</span>(60000, 1000);</code>, then it would pop out 60000. 
519      Now put that with 10000 into <code><span class="object">Math</span>.<span class="function">min</span>(60000, 10000)</code> 
520      and you get 10000 iterations, which is our upper limit.</p> 
521   
522    <h2 id="step7">Step 7: Start the 'iteration' loop</h2> 
523    <p>It's time to start moving the computerized player randomly through the house to test out the layout. We'll start by 
524      setting up two pre-loop variables we need, starting the loop, and then I'm putting in some console displays again 
525      (which you can still leave out if you want).</p> 
526   
527    <p>Let's reset the key list to what it was when the function started and put the fake player into the room.</p> 
528   
529    <div class="code"> 
530      <ul> 
531        <li> 
532          <ul> 
533            <li>foundKeys = <span class="object">player</span>.<span class="property">_tempkeys</span>.<span 
534                class="function">slice</span>(); 
535            </li> 
536            <li><span class="keyword">var</span> playerRoom = playerStart;</li> 
537            <li>&nbsp;</li> 
538            <li><span class="keyword">for</span> (<span class="keyword">var</span> i = 0; i < iterations; i++)</li> 
539            <li>{ 
540              <ul> 
541                <li><span class="object">console</span>.<span class="function">log</span>(<span 
542                    class="string">"*********"</span>); 
543                </li> 
544                <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"iteration: 
545                  "</span> + i); 
546                </li> 
547                <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"location: 
548                  "</span> + playerRoom); 
549                </li> 
550                <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"keys: 
551                  "</span> + foundKeys); 
552                </li> 
553              </ul> 
554            </li> 
555          </ul> 
556        </li> 
557      </ul> 
558    </div> 
559   
560    <h2 id="step8">Step 8: Looking for a key</h2> 
561    <p>For this checker to work, the computer-player needs to pick up a key in any room it's in that has a key. That's 
562      what happens here. We also make sure the computer doesn't end up with hundred of copies of keys. We're not actually 
563      removing them from the rooms because we're not altering the original rooms at all, so each time the computer goes in 
564      the room with the key, it would take another copy!</p> 
565   
566    <p><strong>Be wary.</strong> We're going to get nested pretty deep here, so watch your braces carefully.</p> 
567    <div class="code"> 
568      <ul> 
569        <li> 
570          <ul> 
571            <li> 
572              <ul> 
573                <li><span class="keyword">var</span> <span class="object">room</span> = <span 
574                    class="object">availableRooms</span>[playerRoom]; 
575                </li> 
576                <li><span class="keyword">if</span> (<span class="object">room</span>.<span class="property">keys</span> 
577                  && <span class="object">room</span>.<span class="property">keys</span>.<span 
578                      class="property">length</span> > 0) <span class="comment">//if the room has a key, take it</span> 
579                </li> 
580                <li>{ 
581                  <ul> 
582                    <li><span class="comment">//we don't want to add a hundred of any key, so let's check to make sure we 
583                      don't already have it</span></li> 
584                    <li><span class="keyword">for</span> (<span class="keyword">var</span> k = 0; k < <span 
585                        class="object">room</span>.<span 
586                        class="property">keys</span>.<span class="property">length</span>; k++) 
587                    </li> 
588                    <li>{ 
589                      <ul> 
590                        <li><span class="keyword">var</span> newKey = <span class="object">room</span>.<span 
591                            class="property">keys</span>[k]; 
592                        </li> 
593                        <li><span class="keyword">var</span> keyIndex = foundKeys.<span class="function">indexOf</span>(newKey); 
594                        </li> 
595                        <li><span class="keyword">if</span> (keyIndex === -1) <span class="comment">//we don't have the 
596                          key on the list yet</span> 
597                        <li>{ 
598                          <ul> 
599                            <li>foundKeys.<span class="function">push</span>(newKey);</li> 
600                            <li><span class="object">console</span>.<span class="function">log</span>(<span 
601                                class="string">"Found: "</span> + newKey); 
602                            </li> 
603                          </ul> 
604                        </li> 
605                        <li>}</li> 
606                      </ul> 
607                    </li> 
608                    <li>}</li> 
609                  </ul> 
610                </li> 
611                <li>}</li> 
612              </ul> 
613            </li> 
614          </ul> 
615        </li> 
616      </ul> 
617    </div> 
618   
619    <p>At this point, if there were any keys in this room, you've got them all.</p> 
620   
621    <h2 id="step9">Step 9: Starting the 'exit' loop</h2> 
622    <p>We are still inside the iteration loop, remember. This loop is pretty big because there are a few things we need to 
623      look for. At one point, it's going to get nested even deeper than that last one! Just keep track of those braces and 
624      you'll be fine.</p> 
625   
626    <p>We're going to make a list of possible exits we can choose for later. These will be unlocked doors from the room 
627      we're in. To do that, we will start with an empty array. Then we begin a <code>for...in</code> loop to run through 
628      all the current room's exits.</p> 
629   
630    <h4>Edge cases</h4> 
631    <p>We have one edge case we need to be concerned with. We have to make sure we aren't starting in a room that's 
632      locked, unless we already have its key, or unless the key is in that room. So on the first time through the loop, 
633      when the loop counter, <code>i</code>, is <code>0</code>, we're going to look at the room we're in, look for keys, 
634      check the locks, and if we're stuck, then this test is a bust.</p> 
635   
636    <p>Another edge case we have to watch for is unavailable rooms. It is possible that one of the rooms that was sent in 
637      to the function has an exit to a room that was <em>not</em> sent into the function. Say, for example, we are 
638      checking locks and keys on the first floor, but there's an exit to the second floor and we don't have the list of 
639      rooms from the second floor here. If that happens, we can't check that room.</p> 
640    <p>There's a bit more coming to this loop, but that's enough to get it started. Let's go.</p> 
641   
642    <div class="code"> 
643      <ul> 
644        <li> 
645          <ul> 
646            <li> 
647              <ul> 
648                <li><span class="comment">//check each exit for a locked door and if we can unlock it</span></li> 
649                <li><span class="comment">//we also need to pick an exit at random later, so we're making an array</span> 
650                </li> 
651                <li><span class="keyword">var</span> exitList = [];</li> 
652                <li><span class="keyword">for</span> (<span class="keyword">var</span> exit <span 
653                    class="keyword">in</span> <span class="object">room</span>.<span class="property">exits</span>) 
654                </li> 
655                <li>{ 
656                  <ul> 
657                    <li> 
658                      <span class="keyword">var</span> exitRoom = <span class="object">availableRooms</span>[<span 
659                        class="object">room</span>.<span class="property">exits</span>[exit]]; <span class="comment">//helper 
660                      variable</span></li> 
661                    <li>&nbsp;</li> 
662                    <li><span class="keyword">if</span> (i === 0) <span class="comment">//check the room we start in first 
663                      to make sure it's not locked</span> 
664                    <li>{ 
665                      <ul> 
666                        <li>exitRoom = <span class="object">availableRooms</span>[playerRoom];</li> 
667                      </ul> 
668                    </li> 
669                    <li>}</li> 
670                    <li>&nbsp;</li> 
671   
672                    <li><span class="comment">//the rooms sent in may not have some destinations, so we skip them</span> 
673                    </li> 
674                    <li><span class="keyword">if</span> (!<span class="object">availableRooms</span>[<span class="object">exitRoom</span>.<span 
675                        class="property">name</span>]) 
676                    </li> 
677                    <li>{ 
678                      <ul> 
679                        <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"Not 
680                          available: "</span> + <span class="object">exitRoom</span>.<span class="property">name</span>); 
681                        </li> 
682                        <li><span class="keyword">continue</span>;</li> 
683                      </ul> 
684                    </li> 
685                    <li>}</li> 
686                  </ul> 
687                </li> 
688              </ul> 
689            </li> 
690          </ul> 
691        </li> 
692      </ul> 
693    </div> 
694   
695    <h2 id="step10">Step 10: If it's not locked, it's a possible exit</h2> 
696    <p>After that last step, here's an easy one. We'll make a helper variable that we'll again after this. Remember we 
697      made that list of <code>lockedRooms</code> in the very beginning of the function in that very first loop?</p> 
698   
699    <p>We're going to take the name of the exit we're looking at to see if it's on that locked room list. If it isn't, 
700      then we can assume that it isn't locked and so, it's a safe exit for us.</p> 
701   
702    <p>After this step, we're going to start unlocking rooms and taking room names off that <code>lockedRooms</code> list. 
703      That's how we're simulating the unlocking of rooms without actually messing up the rooms themselves. Sneaky, huh? 
704    </p> 
705   
706    <div class="code"> 
707      <ul> 
708        <li> 
709          <ul> 
710            <li> 
711              <ul> 
712                <li> 
713                  <ul> 
714                    <li><span class="comment">//helper variable</span></li> 
715                    <li><span class="keyword">var</span> lockIndex = lockedRooms.<span 
716                        class="function">indexOf</span>(<span 
717                        class="object">exitRoom</span>.<span class="property">name</span>); 
718                    </li> 
719                    <li><span class="keyword">if</span> (lockIndex === -1) <span class="comment">//if the exit isn't 
720                      locked, we might go that way</span> 
721                    <li>{ 
722                      <ul> 
723                        <li>exitList.<span class="function">push</span>(<span class="object">exitRoom</span>.<span 
724                            class="property">name</span>); 
725                        </li> 
726                      </ul> 
727                    </li> 
728                    <li>}</li> 
729                  </ul> 
730                </li> 
731              </ul> 
732            </li> 
733          </ul> 
734        </li> 
735      </ul> 
736    </div> 
737   
738   
739    <h2 id="step11">Step 11: Is it locked and can we unlock it?</h2> 
740    <p>Now we're at the crux of what we need this function to do: Find locked rooms and try to unlock them.</p> 
741   
742    <p>The problem is... doing that requires quite a bit <em>more</em> nesting. We are already three layers deep. We're 
743      inside the 'exit' loop, which is inside the 'iteration' loop, which is inside the function itself. And here we need 
744      to go further in.</p> 
745   
746    <p>Part of the issue is that it's possible for a room to have more than one key that open it. That means we have to 
747      check all those possibilities, which adds another loop into the mix.</p> 
748   
749   
750    <h3>Here's the plan.</h3> 
751   
752    <ul> 
753      <li>See if the room is locked.</li> 
754      <li>If yes: 
755        <ul> 
756          <li>Loop through the keys that can unlock that room. 
757            <ul> 
758              <li>For each key the room needs, see if we also have that key.</li> 
759              <li>If yes: 
760                <ul> 
761                  <li>Unlock the door by removing it from the <code>lockedRooms</code> array.</li> 
762                  <li>See if the <code>lockedRooms</code> array is empty (all rooms are unlocked)</li> 
763                  <li>If yes: 
764                    <ul> 
765                      <li>Put the keys in your temporary pocket.</li> 
766                      <li>Leave this function, saying it was a success.</li> 
767                    </ul> 
768                  </li> 
769                  <li>If no: 
770                    <ul> 
771                      <li>Add this unlocked room to the possible exit options.</li> 
772                    </ul> 
773                  </li> 
774                </ul> 
775              </li> 
776              <li>If no: 
777                <ul> 
778                  <li>Keep looping through the keys the room needs.</li> 
779                </ul> 
780              </li> 
781            </ul> 
782          </li> 
783        </ul> 
784      </li> 
785      <li>If no: 
786        <ul> 
787          <li>Check any other exits.</li> 
788        </ul> 
789      </li> 
790    </ul> 
791   
792    <p>Here we go.</p> 
793   
794    <div class="code"> 
795      <ul> 
796        <li> 
797          <ul> 
798            <li> 
799              <ul> 
800                <li> 
801                  <ul> 
802                    <li><span class="comment">//let's see if we can unlock the exit and remove it from the locked 
803                      list</span></li> 
804                    <li><span class="keyword">if</span> (<span class="object">exitRoom</span>.<span 
805                        class="property">locked</span> && <span class="object">exitRoom</span>.<span 
806                        class="property">locked</span>.<span class="property">length</span> > 0) 
807                    </li> 
808                    <li>{ 
809                      <ul> 
810                        <li><span class="keyword">for</span> (<span class="keyword">var</span> lock = 0; lock < <span 
811                            class="object">exitRoom</span>.<span class="property">locked</span>.<span class="property">length</span>; 
812                          lock++) 
813                        </li> 
814                        <li>{ 
815                          <ul> 
816                            <li><span class="keyword">var</span> keyNeeded = <span class="object">exitRoom</span>.<span 
817                                class="property">locked</span>[lock]; 
818                            </li> 
819                            <li><span class="keyword">var</span> keyIndex = foundKeys.<span 
820                                class="function">indexOf</span>(keyNeeded); 
821                            </li> 
822                            <li>&nbsp;</li> 
823                            <li><span class="keyword">if</span> (keyIndex >= 0 && lockIndex >= 0) <span class="comment">//we 
824                              have the key and the door is locked</span></li> 
825                            <li>{ 
826                              <ul> 
827                                <li><span class="object">console</span>.<span class="function">log</span>(<span 
828                                    class="string">"Unlocked: "</span> + <span class="object">exitRoom</span>.<span 
829                                    class="property">name</span>); 
830                                </li> 
831                                <li>lockedRooms.<span class="function">splice</span>(lockIndex, 1); <span class="comment">//remove 
832                                  locked room from the list</span></li> 
833                                <li>&nbsp;</li> 
834                                <li><span class="keyword">if</span> (lockedRooms.<span class="property">length</span> === 
835                                  0) <span class="comment">//if no rooms are still locked, we're good</span></li> 
836                                <li>{ 
837                                  <ul> 
838                                    <li><span class="object">player</span>.<span class="property">_tempkeys</span> = 
839                                      foundKeys; <span class="comment">//in case these keys are needed to test other room 
840                                        sets</span></li> 
841                                    <li><span class="keyword">return true</span>;</li> 
842                                  </ul> 
843                                </li> 
844                                <li>}</li> 
845                                <li><span class="keyword">else</span></li> 
846                                <li>{ 
847                                  <ul> 
848                                    <li><span class="object">exitList</span>.<span class="function">push</span>(<span 
849                                        class="object">exitRoom</span>.<span class="property">name</span>); <span 
850                                        class="comment">//now that the room is not locked, we might go that way</span> 
851                                    </li> 
852                                  </ul> 
853                                </li> 
854                                <li>}</li> 
855                              </ul> 
856                            </li> 
857   
858                            <li>} <span class="comment">//closes the unlock door is statement</span></li> 
859                          </ul> 
860                        </li> 
861                        <li>} <span class="comment">//closes the check for all keys that could unlock the door</span></li> 
862                      </ul> 
863                    </li> 
864                    <li>} <span class="comment">//closes the check to see if the exit is locked</span></li> 
865                  </ul> 
866                </li> 
867              </ul> 
868            </li> 
869          </ul> 
870        </li> 
871      </ul> 
872    </div> 
873    <p>Really deep, wasn't it?</p> 
874   
875   
876    <h2 id="step12">Step 12: Finishing the 'exits' loop</h2> 
877    <p>We are getting close to the finish. We have one more detail to tend to before we close up the 'exits' loop.</p> 
878   
879    <p>The first time through the 'iteration' loop, we're just checking the room we're in to make sure we can leave it. If 
880      we can, it will have already been placed on the <code>exitList</code>. But right now, it's trying to loop through 
881      all the exits of that room, so if it has four exits, then this room will end up on that list four times. It's not a 
882      big deal, really, but unnecessary. So, if we're still in the first iteration of the loop, let's break out of it 
883      here, then end the 'exits' loop.</p> 
884   
885    <div class="code"> 
886      <ul> 
887        <li> 
888          <ul> 
889            <li> 
890              <ul> 
891                <li> 
892                  <ul> 
893                    <li><span class="comment">//the first iteration tests the start room itself; we don't need to check 
894                      its exits yet</span></li> 
895                    <li><span class="keyword">if</span> (i === 0)</li> 
896                    <li>{ 
897                      <ul> 
898                        <li><span class="keyword">break</span>;</li> 
899                      </ul> 
900                    </li> 
901                    <li>}</li> 
902                  </ul> 
903                </li> 
904                <li>} <span class="comment">//closes the loop that runs through the current room's possible exits</span> 
905                </li> 
906              </ul> 
907            </li> 
908          </ul> 
909        </li> 
910      </ul> 
911    </div> 
912   
913   
914    <h2 id="step13">Step 13: Closing the 'iteration' loop</h2> 
915    <p>At this point in the function, whatever room the computer-player is in, all the exits have been checked and 
916      possibly unlocked. We have a list of exits we can possibly go to.</p> 
917   
918    <p>Now we need to pick one of the those exits at random&mdash;that's where the name <em>random walk</em> comes from&mdash;and 
919      move the player there to keep the check going.</p> 
920   
921    <div class="code"> 
922      <ul> 
923        <li> 
924          <ul> 
925            <li> 
926              <ul> 
927                <li><span class="comment">//now we have a list of viable exits the player could go into in 
928                  <em>exitList</em></span> 
929                </li> 
930                <li><span class="comment">//let's randomly pick one and make that the new location</span> 
931                <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"Exits: 
932                  "</span> + exitList); 
933                </li> 
934                <li><span class="keyword">if</span> (exitList.<span class="property">length</span> === 0) <span 
935                    class="comment">//there are no exits; the player is trapped, so this check fails</span></li> 
936                <li>{ 
937                  <ul> 
938                    <li><span class="keyword">break</span>;</li> 
939                  </ul> 
940                </li> 
941                <li>}</li> 
942                <li>&nbsp;</li> 
943                <li><span class="keyword">var</span> randomExit = <span class="object">Math</span>.<span class="function">floor</span>(<span 
944                    class="object">Math</span>.<span class="function">random</span>() * exitList.<span class="property">length</span>); 
945                </li> 
946                <li>playerRoom = exitList[randomExit];</li> 
947              </ul> 
948            </li> 
949            <li>} <span class="comment">//end of the random walk 'iteration' loop</span></li> 
950          </ul> 
951        </li> 
952      </ul> 
953    </div> 
954   
955    <h2 id="step14">Step 14: Finishing the function</h2> 
956   
957    <p>Ok, we set the computer-player loose in the rooms, picking up keys and unlocking doors, seeing if it was possible 
958      to unlock them all. If it <em>is</em>, then this function escaped back up when the <code>lockedRooms</code> array 
959      was emptied out.</p> 
960   
961    <p>We just closed the 'iteration' loop a moment ago, so what's left to do? Well, if the function hasn't returned a 
962      successful rating at this point, then it means the computer was not able to unlock everything in the number of steps 
963      (iterations) it had available.</p> 
964   
965    <p>So all that's left is to send that result back and close the function.</p> 
966   
967    <p>We're there... at the end. Let's finish this function!</p> 
968   
969    <div class="code"> 
970      <ul> 
971        <li> 
972          <ul> 
973            <li><span class="object">console</span>.<span class="function">log</span>(<span class="string">"Couldn't 
974              unlock everything."</span>); 
975            </li> 
976            <li><span class="keyword">return false</span>;</li> 
977          </ul> 
978        </li> 
979        <li>}</li> 
980      </ul> 
981    </div> 
982   
983    <h2>What's next?</h2> 
984    <p>That was a lot, but you got to this point. Now you need to test it out. Here's one way.</p> 
985   
986    <ol> 
987      <li>Make sure you have at least one locked room and one key set up in your layout.</li> 
988      <li>Run your game. If you're in the text version, quit when you can.</li> 
989      <li>Get to the console window while your game variables are in memory. 
990        <ul> 
991          <li>In <code>repl.it</code>, click on the console tab.</li> 
992          <li>In a browser, open developer tools. Try pressing <kbd class="key">f12</kbd>.</li> 
993        </ul> 
994      </li> 
995      <li>Call the new function from the console. 
996        <ul> 
997          <li>This will run the default: Full room set based on the player's current room.</li> 
998          <li><code>checkKeys();</code></li> 
999          <li>Or substitute in other values as desired. 
1000         <li>Choose a specific room to start checking from. 
1001           <ul> 
1002             <li><code>checkKeys(rooms, "den", false);</code></li> 
1003           </ul> 
1004         </li> 
1005         <li>Send in a subset of rooms and a starting room (you have to create the <code>firstfloor</code> set first) 
1006           <ul> 
1007             <li><code>checkKeys(firstFloor, "stairway", false);</code></li> 
1008           </ul> 
1009         </li> 
1010         <li>Let the computer pick a random room and test it out 
1011           <ul> 
1012             <li><code>checkKeys(rooms, "", true);</code></li> 
1013             <li>The console will tell you which room was the starting point if you have this line of code in there 
1014               before the iteration loop starts. 
1015               <ul> 
1016                 <li><code><span class="object">console</span>.<span class="function">log</span>(<span class="string">"start 
1017                   room: "</span> + playerStart);</code></li> 
1018               </ul> 
1019             </li> 
1020           </ul> 
1021         </li> 
1022       </ul> 
1023     </li> 
1024     <li>Read the output in the console. 
1025       <ul> 
1026         <li>If it says <span class="keyword">true</span> then it works with the settings you put in. Congrats!</li> 
1027         <li>If it says <span class="keyword">false</span>, it's <em>possible</em> the setup could still be correct. 
1028           <ul> 
1029             <li>This is because we're testing by random walk, not by a tree search.</li> 
1030             <li>You could run it again with the same settings and see if it figures it out a second time.</li> 
1031             <li>But it did run 1000 to 10000 steps through your house... Unless you passed in a lot of rooms at once, 
1032               maybe it just won't work the way it's set up. 
1033             </li> 
1034           </ul> 
1035         </li> 
1036       </ul> 
1037     </li> 
1038     <li>Adjust your locks and keys as needed.</li> 
1039   </ol> 
1040  
1041   <h2>What if I want to use other randomizers?</h2> 
1042   <p>If you plan to use randomizers like <span class="function">randomizeRoomLayout</span>, <span class="function">randomizePlayerStart</span>, 
1043     or <span class="function">randomizeLocksAndKeys</span>, then you'll need to use the <span 
1044         class="function">checkKeys</span> function inside <span class="function">startGame</span>.</p> 
1045  
1046   <p>Here's a quick brute-force solution. It will cause your game to shuffle things a bunch of times until the game is 
1047     playable. That might cause it to hang when you start it up.</p> 
1048  
1049  
1050   <h4>Original code section</h4> 
1051   <p>Inside your <span class="function">startGame</span> function, you have a set of lines that look like this, though 
1052     possibly in a different order and some may be missing if you didn't add certain features.</p> 
1053  
1054   <div class="code"> 
1055     <ul> 
1056       <li><span class="object">rooms</span> = <span class="function">randomizeRoomLayout</span>(<span class="object">rooms</span>); 
1057       </li> 
1058       <li><span class="object">rooms</span> = <span class="function">randomizeBrokenThings</span>(<span class="object">rooms</span>); 
1059       </li> 
1060       <li><span class="function">randomizePlayerStart</span>(<span class="object">rooms</span>);</li> 
1061       <li><span class="function">randomizeItems</span>(<span class="object">rooms</span>);</li> 
1062       <li><span class="function">randomizePoints</span>(<span class="object">rooms</span>);</li> 
1063       <li><span class="object">rooms</span> = <span class="function">randomizeKeys</span>(<span 
1064           class="object">rooms</span>, <span class="keyword">true</span>); 
1065       </li> 
1066     </ul> 
1067   </div> 
1068  
1069   <h4>Reorganize those lines to this</h4> 
1070   <p>We need to group together just the functions that affect the lock and key situation.</p> 
1071  
1072   <div class="code"> 
1073     <ul> 
1074       <li><span class="object">rooms</span> = <span class="function">randomizeRoomLayout</span>(<span class="object">rooms</span>); 
1075       </li> 
1076       <li><span class="object">rooms</span> = <span class="function">randomizeKeys</span>(<span 
1077           class="object">rooms</span>, <span class="keyword">true</span>); 
1078       </li> 
1079       <li><span class="function">randomizePlayerStart</span>(<span class="object">rooms</span>);</li> 
1080       <li>&nbsp;</li> 
1081       <li><span class="object">rooms</span> = <span class="function">randomizeBrokenThings</span>(<span class="object">rooms</span>); 
1082       </li> 
1083       <li><span class="function">randomizeItems</span>(<span class="object">rooms</span>);</li> 
1084       <li><span class="function">randomizePoints</span>(<span class="object">rooms</span>);</li> 
1085     </ul> 
1086   </div> 
1087  
1088   <h4>Wrap the related randomizers in a loop</h4> 
1089   <p>We don't want this to run forever. We want it to break out at some point no matter what. I'm going to have two 
1090     checks. One is an iteration counter and the other is whether we are successful.</p> 
1091  
1092   <p>I'm setting up the two variable first and then wrapping the related function in the loop. The other functions will 
1093     be after the loop. I'm not deleting them.</p> 
1094   <div class="code"> 
1095     <ul> 
1096  
1097       <li><span class="keyword">var</span> successful = <span class="keyword">false</span>;</li> 
1098       <li><span class="keyword">var</span> attempts = 0;</li> 
1099       <li>&nbsp;</li> 
1100       <li><span class="keyword">while</span> (!successful && attempts < 1000)</li> 
1101       <li>{ 
1102         <ul> 
1103           <li><span class="object">rooms</span> = <span class="function">randomizeRoomLayout</span>(<span 
1104               class="object">rooms</span>); 
1105           </li> 
1106           <li><span class="object">rooms</span> = <span class="function">randomizeKeys</span>(<span 
1107               class="object">rooms</span>, <span class="keyword">true</span>); 
1108           </li> 
1109           <li><span class="function">randomizePlayerStart</span>(<span class="object">rooms</span>);</li> 
1110           <li>successful = <span class="function">checkKeys</span>(<span class="object">rooms</span>, <span 
1111               class="object">player</span>.<span class="property">currentRoom</span>.<span class="property">name</span>, 
1112             <span class="keyword">false</span>); 
1113           </li> 
1114           <li>attempts++;</li> 
1115         </ul> 
1116       </li> 
1117       <li>}</li> 
1118       <li>&nbsp;</li> 
1119       <li><span class="keyword">if</span> (!successful)</li> 
1120       <li>{ 
1121         <ul> 
1122           <li><span class="function">alert</span>(<span class="string">"I got stuck and couldn't unlock everything. You 
1123             might want to restart and let me try again."</span>); 
1124           </li> 
1125         </ul> 
1126       </li> 
1127       <li>}</li> 
1128       <li>&nbsp;</li> 
1129       <li><span class="comment">//these function calls are still here from when we sorted them a moment ago</span></li> 
1130       <li><span class="object">rooms</span> = <span class="function">randomizeBrokenThings</span>(<span class="object">rooms</span>); 
1131       </li> 
1132       <li><span class="function">randomizeItems</span>(<span class="object">rooms</span>);</li> 
1133       <li><span class="function">randomizePoints</span>(<span class="object">rooms</span>);</li> 
1134     </ul> 
1135   </div> 
1136  
1137   <h4>alert vs throw</h4> 
1138   <p>Typically, instead of an <span class="function">alert</span>, programmers would use a <span 
1139       class="keyword">throw</span> to cause a "crash" in the browser. It's on purpose, so it's not the same as when 
1140     something goes wrong. The <span class="function">alert</span> is less scary. If want to use the <span 
1141         class="keyword">throw</span>, swap out the <span class="function">alert</span> line with this.</p> 
1142  
1143   <div class="code"> 
1144     <ul> 
1145       <li> 
1146         <ul> 
1147           <li> 
1148             <span class="keyword">throw</span> <span class="string">"I got stuck and couldn't unlock everything. You 
1149             might want to restart and let me try again.";</span> 
1150           </li> 
1151         </ul> 
1152       </li> 
1153     </ul> 
1154   </div> 
1155  
1156   <p>When you <span class="keyword">throw</span> an error, the program stops running completely. There's more you can do 
1157     with <span class="keyword">throw</span>, but we're not getting into it right here.</p> 
1158  
1159   <h4>Simpler success?</h4> 
1160   <p>Because of how we set up our <span class="function">checkKeys</span> function, we could simplify this line as 
1161     shown.</p> 
1162  
1163   <div class="code"> 
1164     <ul> 
1165       <li> 
1166       <li>successful = <span class="function">checkKeys</span>(<span class="object">rooms</span>, <span 
1167           class="object">player</span>.<span class="property">currentRoom</span>.<span class="property">name</span>, 
1168         <span class="keyword">false</span>); 
1169       </li> 
1170       <li> 
1171       <li>successful = <span class="function">checkKeys</span>(); <span class="comment">//much shorter</span></li> 
1172     </ul> 
1173   </div> 
1174   <p>But this is only ok to do if we are using the global set of all rooms. Currently, my code here does. But it's 
1175     better to send in the expected arguments any time you can for readability and code clarity.</p> 
1176  
1177  
1178   <h2>May you always be able to unlock the doors to your future!</h2> 
1179   <h2>&mdash;Dr. Wolf</h2> 
1180  
1181   <div id="prevnext"></div> 
1182   <!-- required section for navigation sidebar --></div> 
1183 <script src="/navigator.js"></script> 
1184 <script>begin("roomadventure");</script> 
1185 <!-- end of required section for navigation sidebar --> 
1186 </body> 
1187 </html> 
1188