ktane-solver
A JavaScript library to solve the vanilla bomb modules from Keep Talking and Nobody Explodes.
📥 Installing
npm i ktane-solver
📖 Terms
- Bomb - the device which holds an amount of modules.
- Modules - a device which contains a single, solvable puzzle which needs to be solved by the Defuser.
- Needy Modules - a device which contains a single, unsolvable puzzle which needs to be regularly tended to by the Defuser.
- Stage - a section or part of a module, indicated by a green LED on the right side of the module.
- Defuser - the person that has sole access to the bomb.
- Expert(s) - the person/people that has/have sole access to the Bomb Defusal Manual.
- "bomb check" - the process of gathering information about the bomb.
- "display number" or "display letter" - the big number/letter at the top of some modules.
💣 The Bomb object
Some modules require information about the bomb in order to solve.
-
digit: int
- the last digit of the serial code. -
vowel: boolean
- if the serial code contains a vowel. -
car: boolean
- if the bomb has a CAR lit indicator. -
frk: boolean
- if the bomb has a FRK lit indicator. -
pport: boolean
- if the bomb has a parallel port. -
batteries: int
- the amount of batteries on the bomb.
Methods
-
add_strike()
- Add a strike to the bomb. -
reset_strikes()
- Reset the bomb's strike count. -
reset_memory()
- Reset the Memory module. This is called automatically after solving the Memory module. -
reset_sequence()
- Reset the Sequence module. This is called automatically after solving the Sequence module.
Example
let bomb = new Bomb(2, true, false, true, true, 1)
This creates a bomb instance that has:
- A serial code with a vowel, and an even number as the last digit
- For example:
AWXYZ2
- For example:
- No CAR lit indicator
- A FRK lit indicator
- A parallel port
- 1 battery
🧩 : Modules
More information about the modules, as well as how to solve them, can be found at the Bomb Defusal Manual.
✂️ Wires
Input
-
wires: Array<String>
- a String array with each wire colour.- Possible colours:
red
,blue
,yellow
,black
,white
- Possible colours:
-
bomb: Object
- an instance of the bomb object.
Output
-
int
- The index of the wire that should be cut based on the array passed, starting from 0.
Throws
- If the amount of wires is incorrect.
Example
import Bomb from "ktane-solver/bomb"
import Wires from "ktane-solver/wires"
let bomb = new Bomb(2, true, false, false, true, 1)
Wires.solve(["red", "blue", "blue"], bomb)
>> 2
🔴 Button
Input for part 1
-
button: String
- a String describing the button's colour and text, in that order.- Possible colours:
red
,blue
,yellow
,black
,white
- Possible texts:
abort
,detonate
,hold
,press
- Possible colours:
-
bomb: Object
- an instance of the bomb object.
Output for part 1
-
String
- What the Defuser should with the button after pressing it.-
"HOLD"
- the button should be pressed and held. -
"RELEASE"
- the button should be pressed and immediately released.
-
Throws
- If either
colour
ortext
are undefined.
Input for part 2
-
strip: String
- a String describing the colour of the strip.- Possible colours:
red
,blue
,yellow
,white
- Possible colours:
Output for part 2
-
String
When the button should be released.-
"1"
- the button should be released when the countdown timer has a 1 in any position. -
"4"
- the button should be released when the countdown timer has a 4 in any position. -
"5"
- the button should be released when the countdown timer has a 5 in any position.
-
Examples
Part 1 example
import Bomb from "ktane-solver/bomb"
import Wires from "ktane-solver/button"
let bomb = new Bomb(2, true, false, false, true, 1)
Button.solvePartOne("red detonate", bomb)
>> "HOLD"
Part 2 example
import Bomb from "ktane-solver/bomb"
import Wires from "ktane-solver/button"
let bomb = new Bomb(2, true, false, false, true, 1)
Button.solvePartTwo("blue")
>> 4
🔑 Keypad
Input
-
symbols: Array<String>
- a String array with each symbol description
Output
-
Array<String>
- The order at which the symbols should be pressed.
Throws
- If exactly 4 symbols aren't passed.
- If any symbol(s) aren't recognised.
- If a solution for the given symbols isn't found.
Example
import Keypad from "ktane-solver/keypad"
Keypad.solve(["kitty", "curly h", "at", "reverse c"])
>> ["at", "kitty", "curly h", "reverse c"]
💬 Simon Says
Input
-
colours: Array<String>
- a String array with each colour.- Possible colours:
red
,blue
,yellow
,green
- Possible colours:
-
bomb: Object
- an instance of the bomb object.
Output
-
Array<String>
- The colours that the Defuser should press, in order.
Example
import Bomb from "ktane-solver/bomb"
import SimonSays from "ktane-solver/simonsays"
let bomb = new Bomb(2, true, false, false, true, 1)
SimonSays.solve(["red", "red", "blue"], bomb)
>> [ "blue", "blue", "red" ]
🗒️ Who's On First
Input
-
word: String
- the display word.
Output for part 1
-
String
- The position of the word on the module, that should be the input for part 2.- Possible positions:
TL
(top left),TR
(top right),ML
(middle left),MR
(middle right),BL
(bottom left),BR
(bottom right)
- Possible positions:
Throws
- If a word is unrecognised.
Input for part 2
-
word: String
- the word, based on the position output from part 1.
Output for part 2
-
String
- A list of possible words, in order. The first word that both appears on the list, and on the module, should be pressed by the Defuser.
Throws
- If a word is unrecognised.
Examples
Part 1 example
import WhosOnFirst from "ktane-solver/whosonfirst"
WhosOnFirst.solvePartOne("says")
>> "BR"
Part 2 example
import WhosOnFirst from "ktane-solver/whosonfirst"
WhosOnFirst.solvePartTwo("right")
>> "YES, NOTHING, READY, PRESS, NO, WAIT, WHAT, RIGHT"
🧠 Memory
Input
-
numbers: Array<int>
- an int array of the module's numbers, starting with the display number, and numbers below, in order from left-to-right. -
bomb: Object
- an instance of the bomb object.
Output
-
int
- The label of the button that the Defuser should press.
Throws
- If the passed array has more than 5 elements.
- If the passed array contains a number that isn't 1, 2, 3, or 4.
Notes
- This module requires knowledge of previous stages, which is held in the bomb object. Make sure to pass the same bomb object in for each stage.
- This module will automatically call
reset_memory()
after the module is solved. You can call this method prematurely if required.
Example
import Bomb from "ktane-solver/bomb"
import Memory from "ktane-solver/memory"
let bomb = new Bomb(2, true, false, false, true, 1)
Memory.solve([4,1,3,4,2], bomb)
Memory.solve([3,3,1,2,4], bomb)
Memory.solve([4,3,1,2,4], bomb)
Memory.solve([2,2,4,1,3], bomb)
Memory.solve([2,2,4,1,3], bomb)
>> 2
>> 3
>> 4
>> 2
>> 3
💡 Morse Code
Input
-
morse: Array<String>
- a String array of Morse Code characters.
Output
-
Array<String>
- A list of the possible words, given the input; -
String
- OR the frequency that should be selected.
Throws
- If the translated word doesn't match to a frequency.
Example
import Morse from "ktane-solver/morse"
Morse.solve(["dot dot dot", "dot dot dot dot", "dot", "dot dash dot dot", "dot dash dot dot"])
>> 3.505
🐍 Complicated Wires
Input
-
wires: Array<String>
- a String array describing the wire colour(s), if there's a star, and if the light is on.- Possible colours, up to 2 at once:
red
,white
,blue
- Possible colours, up to 2 at once:
-
bomb: Object
an instance of the bomb object.
Output
-
Array<boolean>
- A list of Booleans describing if each wire should be cut.-
true
- cut the wire. -
false
- don't cut the wire.
-
Throws
- If a colour is unrecognised.
Notes
-
If there's no star, you don't need to include "star" in the wire description.
-
If the light isn't on, you don't need to include "light" in the wire description.
-
The order of each wire description doesn't matter. i.e.
light red star
,red star light
, andstar light red
are all equivalent and valid inputs. -
The order of each wire colour doesn't matter. i.e.
red blue
andblue red
are the both equivalent and valid inputs.
Example
import Bomb from "ktane-solver/bomb"
import Complicated from "ktane-solver/complicated"
let bomb = new Bomb(2, true, false, false, true, 1)
Complicated.solve(["white star", "red star", "red star", "blue star", "light blue star", "light red white star"], bomb)
>> [ true, true, true, false, true, false ]
🌽 Maze
Input
-
ind: Array<int>
- an int array of the position of either green indicator. -
start: Array<int>
- an int array of the position of the white light. -
end: Array<int>
- an int array of the position of the red triangle.
Output
-
Array<String>
- A list of directions that the Defuser should input into the module.- Possible directions:
UP
,DOWN
,LEFT
,RIGHT
- Possible directions:
Throws
- If the green indicator is unrecognised.
Notes
- Each position counts from 1.
- The position follows the following notation: across first, then down.
- Only one green indicator is required to identify the correct maze.
- This solution uses a modified version of this maze-solving algorithm. Thank you trincot.
Example
import Maze from "ktane-solver/maze"
Maze.solve([3, 5], [6, 4], [1, 5])
>> ['DOWN', 'LEFT', 'UP', 'UP', 'RIGHT', 'UP', 'UP', 'LEFT', 'DOWN', 'LEFT', 'DOWN', 'DOWN', 'DOWN', 'DOWN', 'LEFT', 'LEFT', 'LEFT', 'UP'
]
Based on this maze configuration:
🌈 Wire Sequence
Input
-
wires: Array<String>
- a String array describing the wire colour, and the letter it routes to.- Possible colours:
red
,black
,blue
- Possible letters:
A
,B
,C
- Possible colours:
-
bomb: Object
an instance of the bomb object.
Output
-
Array<boolean>
- A list of Booleans describing if each wire should be cut.-
true
- cut the wire. -
false
- don't cut the wire.
-
Throws
- If a colour is unrecognised.
- If a letter is unrecognised.
Notes
- The number on the left side of the module is not required to solve.
- This module requires knowledge of previous stages, which is held in the bomb object. Make sure to pass the same bomb object in for each stage.
- This module will automatically call
reset_sequence()
after the module is solved. You can call this method prematurely if required.
Example
import Bomb from "ktane-solver/bomb"
import Sequence from "ktane-solver/sequence"
let bomb = new Bomb(2, true, false, false, true, 1)
Sequence.solve(["black a", "black b"], bomb)
Sequence.solve(["red c", "red a", "red c"], bomb)
Sequence.solve(["red a"], bomb)
Sequence.solve(["blue b", "red a", "blue b"], bomb)
>> [ true, false ]
>> [ true, false, false ]
>> [ true ]
>> [ true, false, false ]
⌨️ Password
Input
-
columns: Array<String>
- a String array describing each letter in each column.
Output
-
Array<String>
- A list of the possible passwords
Throws
- If the passed array isn't exactly 5 elements long (pad your input with empty strings, if needs be).
Notes
- Partial inputs (empty strings) are accepted.
- Check if the returned array's length is 1 to determine the password.
Examples
import Password from "ktane-solver/password"
Password.solve(["kqtfhy", "hwjfus", "rinybk", "ynukj", "ipkxvc"])
>> ["THINK"]
import Password from "ktane-solver/password"
Password.solve(["tghus", "", "", "", "tnehr"])
>> [ "GREAT", "HOUSE", "THEIR", "THERE", "THESE", "THREE" ]
🍞 Needy Modules
Only one module, Knob, requires any logic. Venting Gas, and Capacitor Discharge can be handled by the Defuser.
🎛️ Knob
Input
-
lights: String
- the condition of each light.-
1
- the light is on. -
0
- the light is off.
-
Output
-
String
- The direction that the knob should be pointed.
Throws
- If a light sequence is unrecognised.
Notes
- Only the left-hand side of the lights are required to solve this module.
- The order should be left-to-right, top-to-bottom.
Example
import Knob from "ktane-solver/knob"
Knob.solve("101111")
>> RIGHT