npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

ktane-solver

v1.12.0

Published

A library made to solve KTaNE modules

Readme

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