A library made to solve KTaNE modules


Keywords
ktane, bomb, solver
License
ISC
Install
npm install ktane-solver@1.12.0

Documentation

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
  • 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
  • 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
  • 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 or text are undefined.

Input for part 2

  • strip: String - a String describing the colour of the strip.
    • Possible colours: red, blue, yellow, white

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

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
  • 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)

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
  • 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, and star light red are all equivalent and valid inputs.

  • The order of each wire colour doesn't matter. i.e. red blue and blue 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

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
  • 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