- Learn
- Tutorials
- Algorithms
- Binary Search
- 4 Computer Search
4 Computer Search
By the end of this chapter, the safe has two players. Lock a code of your own, and the computer cracks it with the same scanner you use, one STEP at a time. It always tries the middle, and it never sees your code.
The game as it is at the end of this chapter. Click the game to play.
If your game and this chapter part ways, here is the chapter’s finished project. Open it and compare. Or start Chapter 5 from it.
To open it, start Myth Engine, choose File › Open Project... and pick the downloaded file.
4.1 The Idea
For three chapters, the safe has been yours to crack. Now the game turns around.
Click Computer cracks it in the game above, and that tab turns gold. The SCAN button is gone, and LOCK CODE stands in its place. Type 37 and lock it. The display shows dashes, the keypad folds away, and a new line appears beside the safe, in gold: NEXT GUESS: 50.
Press STEP. The computer types 50 on the display and scans it, and the safe answers LOWER THAN 50. Half the strip goes dark at once. The gold line reads NEXT GUESS: 25 now, so press STEP again, and the answer is HIGHER THAN 25. One more press, and the door swings open on 37. SOLVED IN 3 SCANS.
How did it find 37 so fast, when it never saw it? It didn’t guess well. It guessed in the middle, every time.
That’s binary search. Remember Chapter 2’s strip of paper, with a hundred squares? The computer always snips it in the middle, so whichever way the clue points, about half the paper goes. The midpoint is that middle code: the low end plus the high end, halved and rounded down, floor((low + high) / 2).
Count the scans for the slowest kind of code, 100. The computer tries 50. Higher. It tries 75, the middle of 51 to 100. Higher again. Then 88, 94, 97 and 99, each one the middle of what’s left, and at last 100, and the safe opens. Seven scans. For a code from 1 to 100, it never needs more, and a code of 50 takes one.
Two more words. The role says who cracks the safe: you, in the Human role, or the computer, in the Computer role. Setup is a fourth phase of a trial, while you choose the code and the safe waits to be locked.
And Chapter 2 made a promise. Scan Guess was built so that the computer could call it too, and here it does, with Scan Guess unchanged.
4.2 The Plan
- The game starts -> New Safe calls Start New Safe -> a Human trial, as before.
- You press C -> Choose Computer Role switches the roles -> Start Code Setup puts the game in Setup -> roleChosen goes out.
- You press Enter in Setup -> Lock Code seals the code, and the safe is Locked.
- You press Space -> Take a Step asks Choose Midpoint for the middle -> it goes on the display -> Scan Guess scans it.
- A role is chosen -> each piece’s Show In Situation reads its row of the Screen Layout.
- The count
$scanschanges, or the Game State does -> Show Search Readout writes NEXT GUESS, or SOLVED IN. - You press H -> Choose Human Role hands the safe back to you.
- A button is clicked -> Safe Button sends its word -> Button Clicks calls the Function its key calls.
4.3 Set Up
COMMANDS adds three keys: Human on H, Computer on C, and Step on Space. Make them in the Input Manager.
GAME SETTINGS adds Setup, the fourth Game State, after the other three. Initial Game State stays Locked, because the game still begins with you at the keypad.
PLACE THESE is long. Most of it is marked hidden, since those pieces belong to the Computer role and start out of sight. Don’t place anything yet, since none of these Objects exists so far. Each part says when to place its own.
HCSpaceLocked, Unlocked, Exhausted, Setup4.4 A Fresh Trial, Either Way
First come the pieces both roles share. Nothing new shows on the screen in this part, and that’s the point: the game should play as it did.
Every word the computer’s side says goes into Safe Copy, in seven new rows at the bottom.
Scan a guess to get a clue.HIGHER THANLOWER THANUNLOCKED!OUT OF SCANSUse the remaining range.Start a new safe.Code sealed.possibilities remainpossibility remainsHIGHERLOWERUNLOCKEDCan the computer crack your code?Choose a code fromSet and lock a code first.NEXT GUESS:SOLVED INSCANSCANS4.4.1 Reset Trial
A trial can start two ways now. You can ask for a new safe, or you can choose a code for the computer to crack. Both need the same clean slate. The whole range is open, nothing is scanned, the Scan Log is empty, and 50 waits on the display to be replaced.
Start New Safe already did all of that. So that part of it moves into a Function of its own, Reset Trial, which both ways can call. It leaves the code alone. Making a code is the caller’s job.
Rebuild Start New Safe’s familiar reset blocks here, in the order this card gives them.
Starts a fresh trial on the same safe: every code is possible again, nothing has been scanned, the Scan Log is empty, and the keypad display shows the starting entry.
safeStateData StructureSafe State- Variable
$low- Value
data('Safe Settings','Standard Safe','lowestCode')
- Variable
$high- Value
data('Safe Settings','Standard Safe','highestCode')
- Variable
$scans- Value
0
- Variable
$lastGuess- Value
0
- Component Value
safeRules.safeState.clue- Value
0
- Table
Scan Log
- Variable
$entry- Value
data('Safe Settings','Standard Safe','startEntry')
- Component Value
safeRules.safeState.startsNewEntry- Value
true
4.4.2 Start New Safe
Start New Safe gets shorter, though it still draws a new code. Where eight blocks stood, one call to Reset Trial goes in, with safeRules handed on, and the Set Game State and the message stay.
Delete the eight blocks. The remaining line closes over their gap. Add the Reset Trial call between the block that sets the code and Set Game State. Join it with their round handles.
Starts a fresh trial on a new safe in the Human role: draws a new secret code with the engine's random block and resets the trial.
safeStateData StructureSafe State- Action Name
codeRoll- Minimum
data('Safe Settings','Standard Safe','lowestCode')- Maximum
data('Safe Settings','Standard Safe','highestCode')
- Component Value
safeRules.safeState.code- Value
codeRoll.value
- Table
Scan Log
- Variable
$low- Value
data('Safe Settings','Standard Safe','lowestCode')
- Variable
$high- Value
data('Safe Settings','Standard Safe','highestCode')
- Variable
$scans- Value
0
- Variable
$lastGuess- Value
0
- Component Value
safeRules.safeState.clue- Value
0
- Variable
$entry- Value
data('Safe Settings','Standard Safe','startEntry')
- Component Value
safeRules.safeState.startsNewEntry- Value
true
- safeRules
safeRules
- Applies to
safeRules- Game State
Locked
- Variable
$message- Value
data('Safe Copy','Scan a Guess','text')
4.4.3 Start Code Setup
Start Code Setup prepares the safe for your code. The old trial is cleared away, and the message asks the question this whole chapter answers: “Can the computer crack your code?”
Notice what it doesn’t do. It draws no code, because in Setup the code is yours to type.
Starts a fresh trial in the Computer role: the player types the code the computer will crack, then locks it.
safeStateData StructureSafe State- safeRules
safeRules
- Applies to
safeRules- Game State
Setup
- Variable
$message- Value
data('Safe Copy','Choose a Code','text')
Run the game. It plays exactly as it did in Chapter 3, and R deals a new safe, through Reset Trial now.
4.5 The Computer’s Move
Now the heart of binary search. It’s the smallest piece in the game.
4.5.1 Choose Midpoint
Choose Midpoint answers one question about a range, given only its two ends: which code sits in the middle?
Look at its PARAMETERS: low and high. That’s all it gets. It has no safeRules, so Safe State is out of its reach, and the code is nowhere among its values. It can’t peek.
It adds the two ends and halves the sum. Halving can leave a half, and a code is a whole number, so floor rounds it down. Return hands the midpoint back, as a Number.
Answers the computer's next guess for a range of codes: the middle of low and high, rounded down. It is given only the two ends of the range, never the code.
- Name
midpoint- Value
0
- Variable
midpoint- Value
floor((low + high) / 2)
- Value
midpoint
4.5.2 Take a Step
Take a Step is one computer turn, with a gate first, the way Scan Guess has one.
Is the safe Locked? If it isn’t, there’s no code to crack yet, and the message says “Set and lock a code first.” If it is, three things happen in order. Choose Midpoint gets $low and $high, and its answer comes back as nextGuess. That answer goes on the display, in $entry, the very place your own guesses go. And last, Take a Step calls Scan Guess.
That’s Chapter 2’s promise, kept. The computer has no scanner of its own, so it uses yours. It puts a number on the display and scans it, as you do. So everything Scan Guess does for you, it does for the computer: the count, the clue, the range, the marks and the cards.
Makes one computer turn while the safe is Locked: Choose Midpoint picks the next guess from the range, the guess is shown in the entry, and Scan Guess scans it, the same scanner the human uses.
safeStateData StructureSafe State- Action Name
safeIsLocked- Applies to
safeRules- Game State
Locked
safeIsLocked.value == true- Action Name
nextGuess- low
$low- high
$high
- Variable
$entry- Value
nextGuess.value
- safeRules
safeRules
- Variable
$message- Value
data('Safe Copy','No Code Locked','text')
Nothing calls Take a Step yet. By the end of the next part, Space will.
4.6 Two Roles
Next, the safe learns who’s playing, you or the computer, and what each one’s keys should do.
A role isn’t a value stored somewhere. It’s a whole Logic Component on Safe Rules, turned on or off. Human Role says what Enter and R do while you crack the safe, and Computer Role says what they do while the computer does. Only one is ever on.
4.6.1 Lock Code
Lock Code seals your code, and it works only in Setup. Anywhere else, it changes nothing but the message: “Code sealed.”
In Setup, it looks at the display first. Is the number a code the safe can have, from the lowest code to the highest? If it is, it becomes the safe’s code. The entry goes to 0, so the display shows dashes and nobody can read your code off the screen. The safe is Locked, and the message says the code is sealed.
A code outside the range gets a different message. Lock Code builds it with text(), from the words “Choose a code from” and the two ends in Safe Settings. Setup goes on. Type another.
Step 3’s If goes inside step 2’s True line. Use step 2’s Add Inside Then. Step 8 is the inner If’s Else, and step 10 is the outer If’s Else.
Locks the entry as the secret code during Setup, if it is a code the safe can have (from the lowest to the highest code). The safe is then Locked and the computer may start its search.
safeStateData StructureSafe State- Action Name
settingCode- Applies to
safeRules- Game State
Setup
settingCode.value == true$entry >= data('Safe Settings','Standard Safe','lowestCode') && $entry <= data('Safe Settings','Standard Safe','highestCode')- Component Value
safeRules.safeState.code- Value
$entry
- Variable
$entry- Value
0
- Applies to
safeRules- Game State
Locked
- Variable
$message- Value
data('Safe Copy','Code Sealed','text')
- Variable
$message- Value
text(data('Safe Copy','Code Outside the Range','text'), ' ', data('Safe Settings','Standard Safe','lowestCode'), ' to ', data('Safe Settings','Standard Safe','highestCode'), '.')
- Variable
$message- Value
data('Safe Copy','Code Sealed','text')
4.6.2 Human Role
Human Role takes over two Events from older Logic, Enter from Keypad Keys and R from New Safe. Your keys keep their familiar jobs while you crack the safe.
What the controls do while the human cracks the safe: Enter scans the entry and R starts a new safe. Choose Human Role turns this Logic on.
Any Objectself.safeState- safeRules
self
- safeRules
self
4.6.3 Computer Role
Computer Role answers Enter, R and Space in the computer’s way. Enter calls Lock Code. Space calls Take a Step, and R calls Start Code Setup, for a fresh code of your own.
Two Logic Components listening for one key sounds like trouble. It isn’t, since only one of them is ever on.
What the controls do while the computer cracks the safe: Enter locks the code, Space takes one Step, and R goes back to Setup for a new code. Choose Computer Role turns this Logic on.
Any Objectself.safeState- safeRules
self
- safeRules
self
- safeRules
self
Now take the old Events out: Keypad Keys loses its Scan Event, and New Safe loses its New Safe Event. Delete each Event’s block, and the Action under it.
Lets the keyboard work the keypad: the digit keys type a digit, Backspace erases the last digit, and Delete clears the entry. The keypad's buttons call the same Functions. What Enter does depends on the role, so Human Role and Computer Role answer it.
Any Objectself.safeState- safeRules
self- digit
0
- safeRules
self- digit
1
- safeRules
self- digit
2
- safeRules
self- digit
3
- safeRules
self- digit
4
- safeRules
self- digit
5
- safeRules
self- digit
6
- safeRules
self- digit
7
- safeRules
self- digit
8
- safeRules
self- digit
9
- safeRules
self
- safeRules
self
- safeRules
self
Starts the first safe when the game begins, in the Human role.
Any Objectself.safeState- safeRules
self
- safeRules
self
Attach the two roles to Safe Rules. In Attached Logic, turn Computer Role’s switch off, so the game begins in the Human role. The card’s other new line, Choose Role, waits until the end of the next part.
X 0.8, Y 0.8Safe StateLay Out Scan RecordLay Out Scan Record DataCode MarkScan CardCard GuessCard ClueRun the game. Enter still scans, and R still deals a new safe. That’s Human Role answering now, though you can’t tell.
4.7 Changing Hands
Now the keypad learns when to listen, and the safe learns to change hands.
4.7.1 Check Keypad Open
In Chapter 2, the keypad worked only while the safe was Locked. That rule doesn’t fit anymore. In Setup, you type your code. And while the computer searches, the safe is Locked, but the keypad should stay shut, or you could change the display under the computer’s fingers.
So Check Keypad Open asks the real question. It starts with isOpen false, and in Setup, the answer becomes true. While the safe is Locked, it’s true only if Human Role is on.
That second test uses Check Logic Enabled, which asks whether a Logic Component is turned on, on the Object it names. Its Logic Component is a list, so pick Human Role there. The answer comes back as humanCracks, and the If joins the two tests with &&.
It hands back true or false, so its Declare Variable’s Type is Boolean, and its RETURN TYPE too. Step 2 sets isOpen to false a second time. It does no harm. Build it as the card shows. Steps 6, 7, 8 and 10 sit at the very left, after the first If. Add each from the Action List, and Connect to Sequence joins it to the main line.
Answers whether the player may type on the keypad now: while setting a code for the computer (Setup), or while the human cracks a Locked safe.
safeStateData StructureSafe State- Type
Boolean- Name
isOpen- Value
false
- Variable
isOpen- Value
false
- Action Name
settingCode- Applies to
safeRules- Game State
Setup
settingCode.value == true- Variable
isOpen- Value
true
- Action Name
safeIsLocked- Applies to
safeRules- Game State
Locked
- Action Name
humanCracks- Applies to
safeRules- Logic Component
Human Role
safeIsLocked.value == true && humanCracks.value == true- Variable
isOpen- Value
true
- Value
isOpen
4.7.2 Type Digit, Erase Digit and Clear Entry
All three change the same way, at the top only. Their old Check Game State goes, and a call to Check Keypad Open comes in, named keypad. The If stays, with a new condition: keypad.value == true. Everything inside it stays. So does its Otherwise.
Keep the If, and delete the Check Game State block above it. Start now joins straight to the If. Add the call to Check Keypad Open between them, using their round handles. Last, open the If’s condition and change it. Each Description changes a little too. It says the keypad is open now, not the safe Locked.
The cards below show each Function whole, as it ends up. Step 1 is new. Step 2 keeps its If, with a changed condition. Your canvas already holds everything that follows those two steps on each card. Hold each card beside your own, and check the top.
Adds one typed digit to the entry while the keypad is open. The first digit after a finished entry starts a new entry; later digits are added on the right while the entry is below the highest code.
safeStateData StructureSafe State- Action Name
keypad- safeRules
safeRules
keypad.value == truesafeRules.safeState.startsNewEntry == true- Variable
$entry- Value
0
- Component Value
safeRules.safeState.startsNewEntry- Value
false
$entry < data('Safe Settings','Standard Safe','highestCode')- Variable
$entry- Operator
*=- Value
10
- Variable
$entry- Operator
+=- Value
digit
- Variable
$message- Value
data('Safe Copy','Code Sealed','text')
Removes the last digit of the entry (Back) while the keypad is open. The next digit typed is added to what is left.
safeStateData StructureSafe State- Action Name
keypad- safeRules
safeRules
keypad.value == true- Variable
$entry- Value
floor($entry / 10)
- Component Value
safeRules.safeState.startsNewEntry- Value
false
- Variable
$message- Value
data('Safe Copy','Code Sealed','text')
Empties the entry (Clear) while the keypad is open, so the next digit typed is its first digit.
safeStateData StructureSafe State- Action Name
keypad- safeRules
safeRules
keypad.value == true- Variable
$entry- Value
0
- Component Value
safeRules.safeState.startsNewEntry- Value
false
- Variable
$message- Value
data('Safe Copy','Code Sealed','text')
4.7.3 Choose Human Role and Choose Computer Role
These two hand the safe over. They’re mirror images, so once one is built, the other comes quickly.
Choose Computer Role first asks whether Human Role is on. If it isn’t, the computer has the safe already, so nothing happens and the trial goes on.
If Human Role is on, four things happen. Set Logic State turns Human Role off, and a second one turns Computer Role on. That second one has no State line on its card, because Enable is where the State list starts. Start Code Setup puts the game in Setup. And Trigger Custom Event sends roleChosen to every Object that listens for it.
Both Logic Component fields are lists, as on Check Logic Enabled. Pick each name there.
Hands the safe to the computer if the human has it: turns the Human Role Logic off and the Computer Role Logic on, starts Setup for a new code, and sends roleChosen. If the computer already has it, nothing changes.
safeStateData StructureSafe State- Action Name
humanCracks- Applies to
safeRules- Logic Component
Human Role
humanCracks.value == true- Applies to
safeRules- Logic Component
Human Role- State
Disable
- Applies to
safeRules- Logic Component
Computer Role
- safeRules
safeRules
- Custom Event
roleChosen
Choose Human Role is the same, the other way round. It asks about Computer Role, turns that one off and Human Role on, and calls Start New Safe for a fresh safe of your own.
Hands the safe to the human if the computer has it: turns the Computer Role Logic off and the Human Role Logic on, starts a new safe, and sends roleChosen. If the human already has it, nothing changes.
safeStateData StructureSafe State- Action Name
computerCracks- Applies to
safeRules- Logic Component
Computer Role
computerCracks.value == true- Applies to
safeRules- Logic Component
Computer Role- State
Disable
- Applies to
safeRules- Logic Component
Human Role
- safeRules
safeRules
- Custom Event
roleChosen
Nothing listens for roleChosen yet. In the next part, every piece on the screen will.
4.7.4 Choose Role
Choose Role gives the two Functions their keys: H for Choose Human Role, C for Choose Computer Role. Attach it to Safe Rules now, the last new line on Safe Rules’ card.
Lets the keyboard choose the role: H for the Human role, C for the Computer role. The role tabs call the same Functions.
Any Objectself.safeState- safeRules
self
- safeRules
self
Run the game and press C. The message asks whether the computer can crack your code. Type 37 and press Enter, and the display goes to dashes, with your code locked behind them.
Now press Space, and watch the strip. The display reads 50, the message says LOWER THAN 50, and every mark above 50 goes dark. Press Space again for 25, HIGHER THAN 25, and once more, and the safe swings open on 37.
You didn’t type a guess. The computer did, with your scanner, and the strip and the cards followed it the way they follow you.
The screen is a muddle, though. SCAN still shows, the keypad stays out while the computer works, and nothing tells you its next guess. The rest of this chapter puts each piece in its place.
4.8 Each Piece in Its Place
Now the screen learns to change with the role.
Sixteen pieces need to show or hide, by who’s playing and by the phase of the trial. The keypad shows while you crack the safe and while you set a code, but not while the computer searches. LOCK CODE shows only in Setup, and STEP only during the search. Over the display, three captions take turns in one spot: YOUR GUESS, YOUR SECRET CODE and LAST GUESS. It goes on like that, sixteen times.
You could give each piece its own Logic, full of Ifs. That’s sixteen Logic Components to build, and when one is wrong, sixteen places to look.
This is the chapter’s one hard idea. Take it slowly.
The game keeps the whole plan in one table instead, the Screen Layout. It works like the cue sheet a stage crew keeps for a play. Down the side are the pieces, and across the top are the situations the game can be in: human, codeSetup, searching, solved and outOfScans. Each cell answers Yes or No. Does this piece belong on the screen now?
One Logic Component, on every piece, asks the table about its own row. That’s all of it. The table is the plan, and each piece reads its own line.
Make the table first, Screen Layout. Myth makes Screen Layout Entry with it. Open that Data Structure and add its five Boolean fields, one per situation. Then fill the table’s fifteen rows. The Digit Key and the Back Key share the row Keypad. Every cell starts at No, the column’s default, so only the Yes cells need changing. A Boolean cell’s switch turns on for Yes.
One row of the Screen Layout Data Table, made by the engine for the table's rows: human, codeSetup, searching, solved, outOfScans (the table's description says what each column means).
YesYesNoNoNoYesNoNoNoNoYesNoNoNoNoYesNoNoNoNoYesNoNoNoNoNoYesYesYesYesNoYesNoNoNoNoYesNoNoNoNoNoYesYesYesNoNoYesNoNoNoNoYesYesYesNoNoYesYesNoNoNoYesNoYesNoNoYesNoNoNoNoNoYesNo4.8.1 Current Situation
Current Situation names the column. Its answer is a word, one of the table’s five column names, so its Declare Variable and its RETURN TYPE are both Text.
It starts by guessing human, and asks whether Computer Role is on. If it isn’t, human was right. If it is, Current Situation asks about the Game State four times, once for each phase, and the phase that’s true sets the word: codeSetup, searching, solved or outOfScans.
The words go in with their quote marks, such as 'human', because each is a word, not a name.
Inside step 4’s If, every Check Game State after the first follows an If. So steps 8, 11 and 14 go in through step 4’s Add Inside Then, and each joins the end of that True line. The If following each check also joins that True line through the same menu. Step 17, the Return, is back at the very left.
Answers which situation the game is in, as the name of a Screen Layout column: human in the Human role; in the Computer role codeSetup, searching, solved or outOfScans for the phase of the trial.
safeStateData StructureSafe State- Type
Text- Name
situation
- Variable
situation- Value
'human'
- Action Name
computerCracks- Applies to
safeRules- Logic Component
Computer Role
computerCracks.value == true- Action Name
inSetup- Applies to
safeRules- Game State
Setup
inSetup.value == true- Variable
situation- Value
'codeSetup'
- Action Name
inLocked- Applies to
safeRules- Game State
Locked
inLocked.value == true- Variable
situation- Value
'searching'
- Action Name
inUnlocked- Applies to
safeRules- Game State
Unlocked
inUnlocked.value == true- Variable
situation- Value
'solved'
- Action Name
inExhausted- Applies to
safeRules- Game State
Exhausted
inExhausted.value == true- Variable
situation- Value
'outOfScans'
- Value
situation
4.8.2 Show For Situation
Show For Situation shows or hides one piece. It gets the piece, Safe Rules, and the piece’s row name, layoutRow.
It asks Current Situation for the column, as situationNow. The If reads one cell of the table, data('Screen Layout', layoutRow, situationNow.value): this piece’s row, now’s column. On Yes, Set Visible shows the piece. On No, a second Set Visible hides it. On the canvas, Visible reads Yes for the card’s true and No for false.
The piece Parameter is an Object with nothing required, since any piece will do, so leave it as it comes. The layoutRow Parameter is Text, and it starts empty.
Shows or hides one piece for the situation the game is in, as its row of the Screen Layout table says.
safeStateData StructureSafe State- Action Name
situationNow- safeRules
safeRules
data('Screen Layout', layoutRow, situationNow.value) == true- Applies to
piece- Visible
true
- Applies to
piece- Visible
false
4.8.3 Show In Situation
Show In Situation is the Logic every piece carries. It has two Events, and both call Show For Situation with this piece.
Why two? The phase can change while the role stays put, and Game State Changed hears that. But the role can change while the phase stays put, too. Choose Human Role starts a Locked trial, and the computer’s trial may have been Locked already. Locked to Locked is no change. Game State Changed stays silent, so the second Event listens for roleChosen, the word the Choose Role Functions send when the safe changes hands. Nothing listened for it before. Now something does.
Its two Shared Variables let one Logic serve sixteen pieces. The first, safeRules, is the Object to ask. The second, layoutRow, is the piece’s row name, set on each Object’s card. A Shared Variable can be Text as well as an Object, so give that one the Type Text and an empty Starting Value.
Shows this piece only in the situations its row of the Screen Layout table picks (the keypad, the SCAN and LOCK CODE buttons, the computer's readout, and the rest), and hides it otherwise.
Any Object- piece
self- safeRules
@self.safeRules- layoutRow
@self.layoutRow
- piece
self- safeRules
@self.safeRules- layoutRow
@self.layoutRow
Five pieces from earlier chapters get it now: the Digit Key, the Back Key, the YOUR GUESS caption (the Entry Caption), and the SCAN and New safe buttons. Attach Show In Situation to each, and set its layoutRow under Variables. layoutRow is Text, so its Value is a box, not a list. Type the row’s name there, spelled exactly as the table spells it. Four of them have safeRules already, from Type Its Digit or Safe Button. It’s the same one, so leave it. The Entry Caption’s is new, and you pick Safe Rules there.
Window / UIUIX 68, Y 51018Bold#F5E9CACenterVector-1Safe KeyX 68, Y 51Safe RulesKeypadWindow / UIUIX 68, Y 51Back18Bold#F5E9CACenterVector-1Safe KeyX 68, Y 51Safe RulesKeypadbackClickedWindow / UIUIYOUR GUESS12Bold#79C5C4VectorSafe RulesEntry CaptionWindow / UIUIX 146, Y 64SCAN18Bold#F5E9CACenterVector-1Safe GoldX 146, Y 64Safe RulesScan ButtonscanClickedWindow / UIUIX 181, Y 40New safe18Bold#F5E9CACenterVector-1Safe ButtonX 181, Y 40Safe RulesNew Safe ButtonnewSafeClickedThree new pieces carry it from the start. The Human Goal and the Computer Goal take turns as the line under the title. Each Text reads the range and Chapter 2’s scanBudget column from Safe Settings. Keep each card’s spelling and braces. YOUR SECRET CODE, the Code Caption, waits in the same spot as YOUR GUESS.
Window / UIUIFind a hidden code from {data('Safe Settings','Standard Safe','lowestCode')}-{data('Safe Settings','Standard Safe','highestCode')} in {data('Safe Settings','Standard Safe','scanBudget')} scans.16Medium#B5C6CEVectorSafe RulesHuman GoalWindow / UIUIChoose a code from {data('Safe Settings','Standard Safe','lowestCode')}-{data('Safe Settings','Standard Safe','highestCode')}. Binary search gets {data('Safe Settings','Standard Safe','scanBudget')} scans.16Medium#B5C6CEVectorSafe RulesComputer GoalWindow / UIUIYOUR SECRET CODE12Bold#79C5C4VectorSafe RulesCode CaptionPlace these three from PLACE THESE. The Computer Goal and the Code Caption start hidden.
Run the game. Under the title, it says “Find a hidden code from 1-100 in 7 scans.” Press C, and the line changes. SCAN and New safe disappear, and the caption over the display reads YOUR SECRET CODE. Lock a code, and the keypad folds away while the computer takes over. Press H, and everything you had comes back.
From each piece’s point of view, there’s nothing to decide: it knows its own row, and the table knows the rest.
4.9 The Search, Out Loud
Now the computer thinks out loud.
While it searches, a gold line beside the safe says what it will try next, NEXT GUESS: 50, with the sum it came from under it. When the safe opens, the gold line says SOLVED IN 3 SCANS instead.
The line is one Text. It shows three fields of its own Data Structure, Readout Line, as {heading} {number} {unit}, and Logic fills them. Type the braces as the card has them, with no $ and no self. A bare name in braces reads a field of the Object’s own Data Structure, as {words} did on the Possibilities line in Chapter 2.
What the computer's readout line shows, written by Write Search Readout. heading: NEXT GUESS: or SOLVED IN. number: the next guess, or how many scans it took. unit: SCAN or SCANS once solved, otherwise empty.
4.9.1 Write Search Readout
Write Search Readout fills the three fields. Is the safe Unlocked? Then the heading is SOLVED IN, and the number is $scans, with SCAN after a single scan and SCANS after more. Otherwise, it asks Choose Midpoint for the next guess, under the heading NEXT GUESS:, with no unit. Two single quotes, '', make that unit empty. Put both quote marks in the Value box so it has a Text expression.
It doesn’t work the midpoint out by itself. It asks the same Function Take a Step asks. So the guess you read is the guess the computer will make.
Its readout Parameter is Structural and needs Readout Line, the way safeRules needs Safe State. Leave out Check Game State’s Applies to line, as always. The block still has no box for it.
Writes the computer's readout line: NEXT GUESS with the midpoint Choose Midpoint picks from the range, or, once the safe is Unlocked, SOLVED IN with the number of scans.
readoutLineData StructureReadout Line- Action Name
searchSolved- Applies to
readout- Game State
Unlocked
searchSolved.value == true- Component Value
readout.readoutLine.heading- Value
data('Safe Copy','Solved In','text')
- Component Value
readout.readoutLine.number- Value
$scans
$scans == 1- Component Value
readout.readoutLine.unit- Value
data('Safe Copy','One Scan','text')
- Component Value
readout.readoutLine.unit- Value
data('Safe Copy','Several Scans','text')
- Action Name
nextGuess- low
$low- high
$high
- Component Value
readout.readoutLine.heading- Value
data('Safe Copy','Next Guess','text')
- Component Value
readout.readoutLine.number- Value
nextGuess.value
- Component Value
readout.readoutLine.unit- Value
''
4.9.2 Show Search Readout
Show Search Readout sits on the line and calls Write Search Readout, with self as its readout. Game State Changed covers the lock and the win. Variable Changed listens to scans, which changes with every accepted guess. That’s when the readout needs another look.
Keeps the computer's readout line up to date: rewritten whenever the range or the phase can have changed.
Any Objectself.readoutLine- readout
self
- readout
self
The words around the line need no Logic of their own, only Show In Situation. BINARY SEARCH is the Search Title. The Midpoint Formula’s Text does its own sum, from $low and $high. LAST GUESS and FOUND CODE are two more captions for that one spot over the display.
Window / UIUI{heading} {number} {unit}21Bold#F5CD73VectorReadout LineSafe RulesSearch ReadoutWindow / UIUIBINARY SEARCH17Bold#61C6BEVectorSafe RulesSearch TitleWindow / UIUIfloor(({$low} + {$high}) / 2)16Medium#AABCC6VectorSafe RulesMidpoint FormulaWindow / UIUILAST GUESS12Bold#79C5C4VectorSafe RulesLast Guess CaptionWindow / UIUIFOUND CODE12Bold#79C5C4VectorSafe RulesFound Code CaptionPlace all five. Each starts hidden.
Run the game, press C, and lock 37. Beside the safe, it reads BINARY SEARCH and NEXT GUESS: 50, over floor((1 + 100) / 2). Press Space, and the sum becomes floor((1 + 49) / 2), with 25 as the next guess. Keep going until the safe opens.
4.11 If It Didn’t Work
This chapter touches nearly every piece you’ve built, so a slip can show up far from where it happened. That’s normal. Press C, lock a code, and watch which piece misbehaves first.
Pressing C does nothing? Perhaps Choose Role isn’t on Safe Rules, or the Computer Command has no key.
Typing in Setup says “Code sealed.”? Then Check Keypad Open is saying no. Look at its first test, the Check Game State for Setup. In Game Settings, Setup should be the fourth Game State, and Start Code Setup’s Set Game State should pick it.
Enter scans in the Computer role, or locks in the Human role? Then both roles are on, or the wrong one is. In Safe Rules’ Attached Logic, Computer Role’s switch should start off, and each Choose Role Function’s two Set Logic States should pick the right Logic Components.
Space does nothing? Lock a code first, because Take a Step works only while the safe is Locked. If it still does nothing, look at the Step Command’s key, and at Computer Role’s Step Event.
The computer guesses the same number over and over? Look at Take a Step’s call to Choose Midpoint, where low is $low and high is $high, each with its $.
A piece never shows, or never hides? Its layoutRow under Variables should be spelled exactly like its row in the Screen Layout table. And roleChosen should be spelled the same in Trigger Custom Event and in Show In Situation’s Event.
Both tabs gold, or neither? Look at the second placement’s Is Computer Tab, and at the first one’s Sprite, made Safe Gold by Edit Object Locally.
Each of these is one small fix. Make it, press C, and lock a code again. The catch-up download in the Goal is this chapter’s game, finished, if you’d like to compare.
Change how the computer guesses, and watch what happens. In Choose Midpoint, change the formula to low, so it always tries the lowest code still possible. Lock 37 and step. It creeps up one code at a time, and its seven scans run out long before 37. Try high too, or a guess a third of the way along, and count the scans the slowest code takes. Before you start Chapter 5, put it back to floor((low + high) / 2).
The safe has two players now, and one scanner. In Chapter 5, the computer runs by itself, and you watch it crack the very code you cracked a moment before.
