text:
$(function() {
  "use strict";

  var ws = undefined;
  var error = $("div.error");
  var usernameContainer = $(".center-container.username");
  var chatContainer = $(".center-container.chat");

  var username = usernameContainer.find("input[name=username]").focus();
  var usernameButton = username.siblings(".input-group-btn").children("button");

  var postInput = chatContainer.find("input[name=post]");
  var postButton = postInput.siblings(".input-group-btn").children("button");

  var timeline = chatContainer.find(".timeline");

  (function init() {
    usernameButton.on("click", _usernameReady);
    username.on("keyup", _onEnterHit(_usernameReady));

    $(document).on("click", "*:not(input)", function() {
      $("input:visible:first").focus();
    });
  })();

  function _openConnection(username) {
    var protocols = { "http:": "ws:", "https:": "wss:" };
    try {
      var ws = new WebSocket([
        protocols[location.protocol],
        "//",
        location.host,
        "/chat?username=",
        username,
        "&sent=",
        _now()
      ].join(''));

      window.ws = ws;
      ws.onopen = _socketOpened;
      ws.onmessage = _messageArrived;
      ws.onclose = _socketClosed;
      return ws;
    } catch(e) {
      error.removeClass("hide").text("Unable to connect to the websocket. " + data);
      console.log("Unable to connect to the websocket.", e);
      return undefined;
    }
  }

  function _onEnterHit(fn) {
    return function(e) {
      var key = e.key || e.keyCode || e.which;

      if (key === "Enter" || key === 13) {
        e.preventDefault();
        fn();
      }
    };
  }

  function _usernameReady() {
    if (ws) return;

    var name = username.val();

    if (!name || name.trim().length === 0)
      return;

    ws = _openConnection(name);
  }

  function _submit(e) {
    var value = postInput.val();
    if (!value || value.trim().length === 0)
      return;

    var json = {
      sent: _now(),
      message: value
    };

    var self = { data: $.extend({}, json, { received: _now(), processed: _now() }) };
    _messageArrived(self).addClass("self");

    ws.send(JSON.stringify(json));
    postInput.val("").focus();
  }

  function _socketOpened() {
    postInput.attr("disabled", false)
       .on("keyup", _onEnterHit(_submit));
    postButton.on("click", _submit);

    usernameContainer.addClass("hide");
    chatContainer.removeClass("hide");
    error.addClass("hide").empty();

    postInput.focus();
  }

  function _messageArrived(message) {
    var arrived = _now();
    var data = message.data;

    if (typeof data === "string")
      data = JSON.parse(data);

    var post = $("<div>")
      .addClass("post")
      .attr("sent", data.sent)
      .attr("received", data.received)
      .attr("processed", data.processed)
      .attr("arrived", arrived);

    setTimeout(function() {
      var timestamps = $("<div>").addClass("timestamps alert alert-warning");
      timestamps.append(
        $("<div>").addClass("sent").text("Sent: " + data.sent)
      ).append(
        $("<div>").addClass("received")
          .text("Received: " + data.received + " " + _dateDiff(data.sent, data.received))
      ).append(
        $("<div>").addClass("processed")
          .text("Processed: " + data.processed + " " + _dateDiff(data.received, data.processed))
      ).append(
        $("<div>").addClass("arrived")
          .text("Arrived: " + arrived + " " + _dateDiff(data.processed, arrived))
      ).append(
        $("<div>").addClass("roundtrip")
          .text("Roundtrip: " + _dateDiff(data.sent, arrived))
      ).appendTo(post);
    }, 0);

    post.append($("<div>").addClass("message").text(data.message));

    return post.appendTo(timeline);
  }

  function _socketClosed(data) {
    postInput.attr("disabled", true).off("keyup");

    usernameContainer.removeClass("hide");
    chatContainer.addClass("hide");
    timeline.empty();

    var message = ["Channel closed."];
    if ("code" in data)
      message.push(" Code: " + data.code);
    if ("reason" in data)
      message.push(" Reason: " + data.reason);

    error.removeClass("hide").text(message.join(''));
    console.log(message.join(''), data);

    ws = undefined;
  }

  function _now() {
    return moment().utc().format("YYYY-MM-DDTHH:mm:ss.SSS\\Z");
  }

  function _dateDiff(first, second) {
    first = moment(first, "YYYY-MM-DDTHH:mm:ss.SSS\\Z");
    second = moment(second, "YYYY-MM-DDTHH:mm:ss.SSS\\Z");

    return ["(", second.diff(first), " ms)"].join('');
  }
});


text:
local Strategies = {}

local Combat = require "ai.combat"
local Control = require "ai.control"

local Battle = require "action.battle"
local Textbox = require "action.textbox"
local Walk = require "action.walk"

local Data = require "data.data"

local Bridge = require "util.bridge"
local Input = require "util.input"
local Memory = require "util.memory"
local Menu = require "util.menu"
local Player = require "util.player"
local Shop = require "action.shop"
local Utils = require "util.utils"
local json = require "external.json"

local Inventory = require "storage.inventory"
local Pokemon = require "storage.pokemon"

local splitNumber, splitTime = 0, 0
local resetting

local status = {tries = 0, canProgress = nil, initialized = false}
local stats = {}
Strategies.status = status
Strategies.stats = stats
Strategies.updates = {}
Strategies.deepRun = false

local strategyFunctions

-- RISK/RESET

function Strategies.getTimeRequirement(name)
	local timeCalculation = Strategies.timeRequirements[name]
	if timeCalculation then
		return timeCalculation()
	end
end

function Strategies.reboot()
	if emu.framecount() >= 120 then
		client.pause()
		joypad.set({["Power"] = true})
		client.unpause()
		return
	else
		return
	end
end

function Strategies.hardReset(reason, message, extra, wait)
	resetting = true
	if Data.run.seed then
		if extra then
			extra = extra.." | "..Data.run.seed
		else
			extra = Data.run.seed
		end
	end

	local seed = Data.run.seed
	local newmessage = message.." | "..seed

	local f,  err = io.open(RUNS_FILE, "a")
	if f==nil then
		print("Couldn't open file: "..err)
	else
		f:write(newmessage.."\n")
		f:close()
	end

	local map, px, py = Memory.value("game", "map"), Player.position()
	Data.reset(reason, Control.areaName, map, px, py, stats)
	Bridge.chat(message, false, extra, true)

	if Strategies.elite4Reason then
		Bridge.guessResults("elite4", Strategies.elite4Reason)
		Strategies.elite4Reason = nil
	end

	if Strategies.deepRun then
		p("", true)
		p("", true)
		p("", true)
	end

	if wait and INTERNAL and not STREAMING_MODE then
		strategyFunctions.wait()
	else
		Strategies.reboot()
	end
	return true
end

function Strategies.reset(reason, explanation, extra, wait)
	local time = Utils.elapsedTime()
	local resetMessage = "Reset"
	resetMessage = resetMessage.." at "..Control.areaName
	if time then
		resetMessage = resetMessage.." | "..time
	end
	local separator = " | "

	resetMessage = resetMessage..separator.." "..explanation.."."

	if Strategies.updates.victory and not Control.yolo then
		Strategies.tweetProgress(Utils.capitalize(resetMessage))
	end

	return Strategies.hardReset(reason, resetMessage, extra, wait)
end

function Strategies.death(extra)
	local reason, explanation
	if Control.missed then
		explanation = "Missed"
		reason = "miss"
	elseif Control.wantedPotion then
		explanation = "Ran out of potions"
		reason = "potion"
	elseif Control.criticaled then
		explanation = "Critical'd"
		reason = "critical"
	elseif Combat.sandAttacked() then
		explanation = "Sand-Attack'd"
		reason = "accuracy"
	elseif Combat.isConfused() then
		explanation = "Confusion'd"
		reason = "confusion"
	elseif Combat.isSleeping() then
		explanation = "Slumbering"
		reason = "sleep"
	elseif Control.yolo then
		explanation = "Yolo strats"
		reason = "yolo"
	else
		explanation = "Died"
		reason = "death"
	end
	return Strategies.reset(reason, explanation, extra)
end

function Strategies.overMinute(min)
	if type(min) == "string" then
		min = Strategies.getTimeRequirement(min)
	end
	return min and Utils.igt() > (min * 60)
end

function Strategies.resetTime(timeLimit, explanation, custom)
	if Strategies.overMinute(timeLimit) then
		if RESET_FOR_TIME then
			if not custom then
				explanation = "Took too long to "..explanation
			end
			return Strategies.reset("time", explanation)
		end
	end
end

function Strategies.setYolo(name, forced)
	local minimumTime = Strategies.getTimeRequirement(name)
	if minimumTime and (forced or RESET_FOR_TIME) then
		local shouldYolo = BEAST_MODE or Strategies.overMinute(minimumTime)
		if Control.yolo ~= shouldYolo then
			Control.yolo = shouldYolo
			Control.setYolo(shouldYolo)
			local prefix
			if Control.yolo then
				prefix = "en"
			else
				prefix = "dis"
			end
			--print("YOLO "..prefix.."abled at "..Control.areaName)
		end
	end
	return Control.yolo
end

function Strategies.paceMessage(time)
	Strategies.pbPace = not Strategies.overMinute(time)
	return Utils.elapsedTime(), Strategies.pbPace and " (PB pace)" or ""
end

-- HELPERS

function Strategies.tweetProgress(message, progress)
	if progress then
		Strategies.updates[progress] = true
		message = message.." Pokemon "..Utils.capitalize(Data.gameName).." http://www.twitch.tv/therealpokiemaniak"
	end
	Bridge.tweet(message)
	return true
end

function Strategies.initialize(once)
	if not once then
		once = "initialized"
	end
	if not status[once] then
		status[once] = true
		return true
	end
end

function Strategies.chat(once, message)
	if Strategies.initialize(once) then
		Bridge.chat(message)
	end
end

function Strategies.canHealFor(damage, allowAlreadyHealed, allowFullRestore)
	if type(damage) == "string" then
		damage = Combat.healthFor(damage)
	end
	local curr_hp, max_hp = Combat.hp(), Combat.maxHP()
	if allowAlreadyHealed and curr_hp > math.min(damage, max_hp - 1) then
		return true
	end
	if max_hp - curr_hp > 3 then
		local healChecks = {"super_potion", "potion"}
		if allowFullRestore then
			table.insert(healChecks, 1, "full_restore")
		end
		for __,potion in ipairs(healChecks) do
			if Inventory.contains(potion) and Utils.canPotionWith(potion, damage, curr_hp, max_hp) then
				return potion
			end
		end
	end
end

function Strategies.hasSupersFor(damage)
	local healTo = math.min(Combat.healthFor(damage), Combat.maxHP())
	return Inventory.count("super_potion") >= math.ceil((healTo - Combat.hp()) / 50)
end

function Strategies.hasHealthFor(opponent, extra, allowFull)
	if not extra then
		extra = 0
	end
	local max_hp = Combat.maxHP()
	local afterHealth = math.min(Combat.hp() + extra, max_hp)
	if allowFull and afterHealth == max_hp then
		return true
	end
	return afterHealth > Combat.healthFor(opponent)
end

function Strategies.trainerBattle()
	local battleStatus = Memory.value("game", "battle")
	if battleStatus > 0 then
		if battleStatus == 2 then
			Strategies.initialize("foughtTrainer")
			return true
		end
		Battle.handleWild(battleStatus)
	else
		Textbox.handle()
	end
end

local function interact(direction, extended)
	if Battle.handleWild() then
		if Battle.isActive() then
			return true
		end
		if Textbox.isActive() then
			if status.interacted then
				return true
			end
			Input.cancel()
		else
			if status.attempts and status.attempts > 0 then
				status.attempts = status.attempts - 1
			elseif Player.interact(direction, extended) then
				status.interacted = true
				status.attempts = Data.yellow and 2 or 1
			end
		end
	end
end

function Strategies.buffTo(buff, defLevel, forced)
	if Strategies.trainerBattle() then
		if not Battle.opponentDamaged() then
			if defLevel and Memory.double("battle", "opponent_defense") > defLevel then
				forced = buff
			end
		end
		Battle.automate(forced, true)
	elseif status.foughtTrainer then
		return true
	end
end

function Strategies.dodgeUp(npc, sx, sy, dodge, offset)
	if not Battle.handleWild() then
		return false
	end
	local px, py = Player.position()
	if py < sy - 1 then
		return true
	end
	local wx, wy = px, py
	if py < sy then
		wy = py - 1
	elseif px == sx or px == dodge then
		if px - Memory.raw(npc) == offset then
			if px == sx then
				wx = dodge
			else
				wx = sx
			end
		else
			wy = py - 1
		end
	end
	Walk.step(wx, wy)
end

local function dodgeSideways(options)
	local left = 1
	if options.left then
		left = -1
	end
	local px, py = Player.position()
	if px * left > (options.sx + (options.dist or 1)) * left then
		return true
	end
	local wx, wy = px, py
	if px * left > options.sx * left then
		wx = px + 1 * left
	elseif py == options.sy or py == options.dodge then
		if px + left == options.npcX and py - Memory.raw(options.npc) == options.offset then
			if py == options.sy then
				wy = options.dodge
			else
				wy = options.sy
			end
		else
			wx = px + 1 * left
		end
	end
	Walk.step(wx, wy)
end

function Strategies.completedMenuFor(data)
	if status.cancel then
		return true
	end
	local count = Inventory.count(data.item)
	return count == 0 or (not data.all and status.startCount and count < status.startCount)
end

function Strategies.closeMenuFor(data)
	if data.chain or (not status.menuOpened and not data.close) then
		if Menu.onPokemonSelect() or Menu.hasTextbox() then
			Input.press("B")
			return false
		end
		return true
	end
	return Menu.close()
end

function Strategies.useItem(data)
	if not status.startCount then
		status.startCount = Inventory.count(data.item)
	end
	if not data.item or Strategies.completedMenuFor(data) then
		return Strategies.closeMenuFor(data)
	end
	if Menu.pause() then
		status.menuOpened = true
		Inventory.use(data.item, data.poke)
	end
end

function Strategies.tossItem(...)
	if not status.startCount then
		status.startCount = Inventory.count()
	elseif Inventory.count() < status.startCount then
		return true
	end
	local tossItem = Inventory.contains(...)
	if not tossItem then
		--p("Nothing available to toss", ...)
		return true
	end
	if tossItem ~= status.toss then
		status.toss = tossItem
		--p("Tossing "..tossItem.." to make space", Inventory.count())
	end
	if not Inventory.useItemOption(tossItem, nil, 1) then
		if Menu.pause() then
			Input.press("A")
		end
	end
end

local function completedSkillFor(data)
	if data.map then
		if data.map ~= Memory.value("game", "map") then
			return true
		end
	elseif data.x or data.y then
		local px, py = Player.position()
		if data.x == px or data.y == py then
			return true
		end
	elseif data.done then
		if Memory.raw(data.done) > (data.val or 0) then
			return true
		end
	elseif status.tries > 0 and not Menu.isOpened() then
		return true
	end
	return false
end

function Strategies.isPrepared(...)
	if not status.preparing then
		return false
	end
	for __,name in ipairs(arg) do
		local currentCount = Inventory.count(name)
		if currentCount > 0 then
			local previousCount = status.preparing[name]
			if previousCount == nil or currentCount == previousCount then
				return false
			end
		end
	end
	return true
end

function Strategies.prepare(...)
	if not status.preparing then
		status.preparing = {}
	end
	local item
	for __,name in ipairs(arg) do
		local currentCount = Inventory.count(name)
		local needsItem = currentCount > 0
		local previousCount = status.preparing[name]
		if previousCount == nil then
			status.preparing[name] = currentCount
		elseif needsItem then
			needsItem = currentCount == previousCount
		end
		if needsItem then
			item = name
			break
		end
	end
	if not item then
		return true
	end
	if Battle.isActive() then
		Inventory.use(item, nil, true)
	else
		Input.cancel()
	end
end

function Strategies.getsSilphCarbosSpecially()
	return Data.yellow and Utils.match(stats.nidoran.speedDV, {11, 15})
end

function Strategies.needsCarbosAtLeast(count)
	local speedDV = stats.nidoran.speedDV
	local carbosRequired = 0
	if Data.yellow then
		if speedDV <= 7 then
			carbosRequired = 0
		elseif speedDV <= 8 then
			carbosRequired = 3
		elseif speedDV <= 10 then
			carbosRequired = 2
		elseif Strategies.getsSilphCarbosSpecially() then
			carbosRequired = 1
		end
	else
		if speedDV <= 6 then
			carbosRequired = 3
		elseif speedDV <= 7 then
			carbosRequired = 2
		elseif speedDV <= 9 then
			carbosRequired = 1
		end
	end
	return count <= carbosRequired
end

local function nidokingStats()
	local att = Pokemon.index(0, "attack")
	local def = Pokemon.index(0, "defense")
	local spd = Pokemon.index(0, "speed")
	local scl = Pokemon.index(0, "special")
	local statDesc = att.." "..def.." "..spd.." "..scl
	local attDV, defDV, spdDV, sclDV = Pokemon.getDVs("nidoking")
	stats.nidoran = {
		attack = att,
		defense = def,
		speed = spd,
		special = scl,
		level4 = stats.nidoran.level4,
		rating = stats.nidoran.rating,
		attackDV = attDV,
		defenseDV = defDV,
		speedDV = spdDV,
		specialDV = sclDV,
	}

	Combat.factorPP(false, false)
	Combat.setDisableThrash(false)

	--p(attDV, defDV, spdDV, sclDV)
	--print(statDesc)
	Bridge.stats(statDesc)
end

function Strategies.completeCans()
	local px, py = Player.position()
	if px == 4 and py == 6 then
		--[[local trashcanTries = status.tries + 1
		local prefix
		local suffix = "!"
		if trashcanTries <= 1 then
			prefix = "PERFECT"
		elseif trashcanTries <= (Data.yellow and 2 or 3) then
			prefix = "Amazing"
		elseif trashcanTries <= (Data.yellow and 4 or 6) then
			prefix = "Great"
		elseif trashcanTries <= (Data.yellow and 6 or 9) then
			prefix = "Good"
		elseif trashcanTries <= (Data.yellow and 10 or 22) then
			prefix = "Ugh"
			suffix = "."
		else -- TODO trashcans WR
			prefix = "Reset me now"
			suffix = " BibleThump"
		end
		--Bridge.chat(" "..prefix..", "..trashcanTries.." try Trashcans"..suffix)

		--Bridge.guessResults("trash", trashcanTries)

		local timeLimit = Strategies.getTimeRequirement("trash") + 1
		if Combat.inRedBar() then
			timeLimit = timeLimit + 0.5
		end
		if Strategies.resetTime(timeLimit, "complete Trashcans") then
			return true
		end--]]
		Strategies.setYolo("trash")
		return true
	end
	local completePath = {
		Down = {{2,11}, {8,7}},
		Right = {{2,12}, {3,12}, {1,6}, {2,6}, {3,6}},
		Left = {{9,8}, {8,8}, {7,8}, {6,8}, {5,8}, {9,10}, {8,10}, {7,10}, {6,10}, {5,10}, {}, {}, {}, {}, {}, {}},
	}
	local walkIn = "Up"
	for dir,tileset in pairs(completePath) do
		for __,tile in ipairs(tileset) do
			if px == tile[1] and py == tile[2] then
				walkIn = dir
				break
			end
		end
	end
	Input.press(walkIn, 0)
end

local function hasEnoughHornDrills()
	local earthquakeJinx = stats.nidoran.attackDV >= 11 and Battle.pp("earthquake") > 0
	return Battle.pp("horn_drill") >= (earthquakeJinx and 4 or 5)
end

local function hasEnoughPPItemsToSkipCentering(afterRestoring, afterPickup)
	if afterRestoring and not hasEnoughHornDrills() then
		return false
	end
	local restoresRequired
	if afterRestoring then
		restoresRequired = afterPickup and 2 or 1
	else
		restoresRequired = 2
	end
	return Inventory.ppRestoreCount() >= restoresRequired
end

function Strategies.requiresE4Center(afterRestoring, afterPickup)
	if not hasEnoughPPItemsToSkipCentering(afterRestoring, afterPickup) then
		return true
	end

	if Control.areaName == "Elite Four" then
		return not Strategies.hasHealthFor("LoreleiDewgong")
	end
	return not Strategies.hasSupersFor("LoreleiDewgong")
end

local function useEtherInsteadOfCenter()
	return not hasEnoughHornDrills() and not Strategies.requiresE4Center(false, false)
end

local function requiresMaxEther()
	return Inventory.ppRestoreCount() < (Strategies.requiresE4Center(true, false) and 2 or 3)
end

-- GENERALIZED STRATEGIES

Strategies.functions = {

	tweetBrock = function()
		local statRequirement, timeRequirement
		if stats.nidoran.rating == nil then
			statRequirement = 3
			timeRequirement = "shorts"
			p("Something Fucked up! Should not be here!")
		elseif Data.yellow then
			statRequirement = Pokemon.inParty("pidgey") and stats.nidoran.attack == 16 or stats.nidoran.speed == 15 --TODO
			timeRequirement = "brock"
		else
			statRequirement = stats.nidoran.rating < 2
			timeRequirement = "shorts"
		end
		if statRequirement and not Strategies.overMinute(timeRequirement) then
			Strategies.tweetProgress("On pace after Brock with a great Nidoran in", "brock")
		end
		return true
	end,

	tweetMisty = function()
		Strategies.setYolo("misty")

		if not Strategies.updates.brock and not Control.yolo and (not Combat.inRedBar() or Inventory.contains("potion")) then
			local timeLimit = Strategies.getTimeRequirement("misty")
			if not Strategies.overMinute(timeLimit) then
				local elt, pbn = Strategies.paceMessage(timeLimit - 1)
				Strategies.tweetProgress("Got a run going, just beat Misty "..elt.." in"..pbn, "misty")
			end
		end
		return true
	end,

	tweetSurge = function()
		Control.preferredPotion = "super"

		if not Strategies.updates.misty then
			local timeLimit = Strategies.getTimeRequirement("trash")
			if not Strategies.overMinute(timeLimit + (not Data.yellow and 1.0 or 0.5)) then
				local elt, pbn = Strategies.paceMessage(timeLimit + (not Data.yellow and 0.25 or 0))
				Strategies.tweetProgress("Got a run going, just beat Surge "..elt.." in"..pbn, "surge")
			end
		end
		return true
	end,

	tweetVictoryRoad = function()
		local elt, pbn = Strategies.paceMessage("victory_road")
		Strategies.tweetProgress("Entering Victory Road at "..elt..pbn.." on our way to the Elite Four in", "victory")
		return true
	end,

	bicycle = function()
		if Memory.value("player", "bicycle") == 1 then
			if Menu.close() then
				return true
			end
		else
			return Strategies.useItem({item="bicycle"})
		end
	end,

	frames = function(data)
		if data.report then
			p("FR", Strategies.frames, Utils.frames() - Strategies.startFrames)
			local repels = Memory.value("player", "repel")
			if repels > 0 then
				print("S "..repels)
			end
			Strategies.frames = nil
		else
			Strategies.startFrames = Utils.frames()
			Strategies.frames = 0
		end
		return true
	end,

	split = function(data)
		Data.increment("reset_split")

		Bridge.split(data and data.finished)
		if Strategies.replay or not INTERNAL then
			splitNumber = splitNumber + 1

			local timeDiff
			splitTime, timeDiff = Utils.timeSince(splitTime)
			if timeDiff then
				print(splitNumber..". "..Control.areaName..": "..Utils.elapsedTime())
			end
		end
		return true
	end,

	interact = function(data)
		return interact(data.dir, data.long)
	end,

	talk = function(data)
		return interact(data.dir, data.long)
	end,

	take = function(data)
		return interact(data.dir, data.long)
	end,

	dialogue = function(data)
		if Battle.handleWild() then
			if Textbox.isActive() then
				if Input.cancel(data.decline and "B" or "A") then
					status.talked = true
				end
			else
				if status.talked then
					return true
				end
				Player.interact(data.dir, false)
			end
		end
	end,

	item = function(data)
		if Battle.handleWild() then
			if status.cancel or data.full and not Inventory.isFull() then
				return Strategies.closeMenuFor(data)
			end
			if not status.checked and data.item ~= "carbos" and not Inventory.contains(data.item) then
				print("No "..data.item.." available!")
			end
			status.checked = true
			return Strategies.useItem(data)
		end
	end,

	potion = function(data)
		if not Battle.handleWild() then
			return false
		end
		if not status.cancel then
			local curr_hp = Combat.hp()
			if curr_hp == 0 then
				return false
			end
			local toHP
			if Control.yolo and data.yolo ~= nil then
				toHP = data.yolo
			else
				toHP = data.hp
			end
			if type(toHP) == "string" then
				toHP = Combat.healthFor(toHP)
			end

			local max_hp = Combat.maxHP()
			if status.didPotion and data.topOff then
				toHP = math.max(toHP, max_hp - 49)
			end
			toHP = math.min(toHP, max_hp)

			local toHeal = toHP - curr_hp
			if toHeal > 0 then
				local toPotion
				if data.forced then
					toPotion = Inventory.contains(data.forced)
				else
					local p_first, p_second, p_third
					if toHeal > 50 then
						if data.full then
							p_first = "full_restore"
						else
							p_first = "super_potion"
						end
						p_second, p_third = "super_potion", "potion"
					else
						if toHeal > 20 then
							p_first, p_second = "super_potion", "potion"
						else
							p_first, p_second = "potion", "super_potion"
						end
						if data.full then
							p_third = "full_restore"
						end
					end
					toPotion = Inventory.contains(p_first, p_second, p_third)
				end

				Control.wantedPotion = toPotion == nil
				if toPotion then
					if Menu.pause() then
						status.didPotion = true
						Inventory.use(toPotion)
						status.menuOpened = true
					end
					return false
				end
			end
		end
		if Strategies.closeMenuFor(data) then
			return true
		end
	end,

	teach = function(data)
		if Strategies.initialize("teaching") then
			if not status.cancel then
				status.cancel = data.full and not Inventory.isFull()
			end
		end

		local itemName
		if data.item then
			itemName = data.item
		else
			itemName = data.move
		end
		if not status.cancel then
			if Pokemon.hasMove(data.move) then
				if data.chain and Memory.value("menu", "main") == 128 then
					return true
				end
				status.cancel = true
			else
				local teachTo = data.poke
				if Strategies.initialize("triedTeaching") then
					if not Inventory.contains(itemName) then
						local errorMessage = "Unable to teach move "..itemName
						if teachTo and type(teachTo) == "string" then
							errorMessage = errorMessage.." to "..teachTo
						end
						return Strategies.reset("error", errorMessage, nil, true)
					end
				end
				local replacement
				if data.replace then
					replacement = Pokemon.moveIndex(data.replace, teachTo)
					if replacement then
						replacement = replacement - 1
					else
						replacement = 0
					end
				else
					replacement = 0
				end
				if Inventory.teach(itemName, teachTo, replacement) then
					status.menuOpened = true
				else
					Menu.pause()
				end
			end
		end
		if status.cancel then
			return Strategies.closeMenuFor(data)
		end
	end,

	skill = function(data)
		if completedSkillFor(data) then
			if Data.yellow then
				if not Menu.hasTextbox() then
					return true
				end
			else
				if not Menu.isOpened() then
					return true
				end
			end
			Input.press("B")
		elseif not data.dir or Player.face(data.dir) then
			if Pokemon.use(data.move, Data.yellow) then
				status.tries = status.tries + 1
			elseif Data.yellow and Menu.hasTextbox() then
				Textbox.handle()
			else
				Menu.pause()
			end
		end
	end,

	fly = function(data)
		if Memory.value("game", "map") == data.map then
			return true
		end
		local cities = {
			pallet = {62, "Up"},
			viridian = {63, "Up"},
			lavender = {66, "Down"},
			celadon = {68, "Down"},
			fuchsia = {69, "Down"},
			cinnabar = {70, "Down"},
			saffron = {72, "Down"},
		}

		local main = Memory.value("menu", "main")
		if main == (Data.yellow and 144 or 228) then
			local currentCity = Memory.value("game", "fly")
			local destination = cities[data.dest]
			local press
			if destination[1] - currentCity == 0 then
				press = "A"
			else
				press = destination[2]
			end
			Input.press(press)
		elseif not Pokemon.use("fly", Data.yellow) then
			Menu.pause()
		end
	end,

	swap = function(data)
		if not status.firstIndex then
			local itemIndex = data.item
			if type(data.item) == "string" then
				itemIndex = Inventory.indexOf(data.item)
				status.checkItem = data.item
			end
			local destIndex = data.dest
			if type(data.dest) == "string" then
				destIndex = Inventory.indexOf(data.dest)
				status.checkItem = data.dest
			end
			if destIndex < itemIndex then
				status.firstIndex = destIndex
				status.lastIndex = itemIndex
			else
				status.firstIndex = destIndex
				status.lastIndex = itemIndex
			end
			status.startedAt = Inventory.indexOf(status.checkItem)
		end
		local swapComplete
		if status.firstIndex == status.lastIndex then
			swapComplete = true
		elseif status.firstIndex < 0 or status.lastIndex < 0 then
			swapComplete = true
		elseif status.startedAt ~= Inventory.indexOf(status.checkItem) then
			swapComplete = true
		end

		if swapComplete then
			return Strategies.closeMenuFor(data)
		end

		local main = Memory.value("menu", "main")
		if main == 128 then
			if Menu.getCol() ~= 5 then
				Menu.select(2, true)
			else
				local selection = Memory.value("menu", "selection_mode")
				if selection == 0 then
					if Menu.select(status.firstIndex, "accelerate", true, nil, true) then
						Input.press("Select")
					end
				else
					if Menu.select(status.lastIndex, "accelerate", true, nil, true) then
						Input.press("Select")
					end
				end
			end
		else
			Menu.pause()
		end
	end,

	acquire = function(data)
		Bridge.caught(data.poke)
		return true
	end,

	swapMove = function(data)
		return Battle.swapMove(data.move, data.to)
	end,

	wait = function()
		print("Please save state")
		Input.press("Start", 999999999)
	end,

	waitToTalk = function()
		if Battle.isActive() then
			status.canProgress = false
			Battle.automate()
		elseif Textbox.isActive() then
			status.canProgress = true
			Input.cancel()
		elseif status.canProgress then
			return true
		end
	end,

	waitToPause = function()
		if Menu.pause() then
			return true
		end
	end,

	waitToFight = function(data)
		if Battle.isActive() then
			status.canProgress = true
			Battle.automate()
		elseif status.canProgress then
			return true
		elseif Textbox.handle() then
			if data.dir then
				Player.interact(data.dir, false)
			else
				Input.cancel()
			end
		end
	end,

	leer = function(data)
		if Strategies.trainerBattle() then
			local bm = Combat.bestMove()
			if not bm or bm.minTurns < 3 then
				Battle.automate(data.forced)
				return false
			end
			local opp = Battle.opponent()
			local defLimit = 9001
			local forced
			for __,poke in ipairs(data) do
				if opp == poke[1] then
					local minimumAttack = poke.minAttack
					if not minimumAttack or stats.nidoran.attack > minimumAttack then
						defLimit = poke[2]
					end
					forced = poke.forced
					break
				end
			end
			return Strategies.buffTo("leer", defLimit, forced)
		elseif status.foughtTrainer then
			return true
		end
	end,

	fightX = function(data)
		return Strategies.prepare("x_"..data.x)
	end,

	elixer = function(data)
		local currentPP = Pokemon.pp(0, data.move)
		if currentPP >= data.min then
			return Strategies.closeMenuFor(data)
		end

		data.item = "elixer"
		return Strategies.useItem(data)
	end,

	speedchange = function(data)
		client.speedmode(data.speed)
		return true
	end,

	-- ROUTE

	squirtleIChooseYou = function()
		if Pokemon.inParty("squirtle") then
			Bridge.caught("squirtle")
			return true
		end
		if Player.face("Up") then
			Textbox.PokemonName(false)
		end
	end,

	fightBulbasaur = function()
		if status.tries < 9000 and Pokemon.index(0, "level") == 6 then
			if status.tries > 200 then
				status.tries = 9001

				local attDV, defDV, spdDV, sclDV = Pokemon.getDVs("squirtle")
				local attack, defense, speed, special = Pokemon.index(0, "attack"), Pokemon.index(0, "defense"), Pokemon.index(0, "speed"), Pokemon.index(0, "special")
				stats.starter = {
					attack = Pokemon.index(0, "attack"),
					defense = Pokemon.index(0, "defense"),
					speed = Pokemon.index(0, "speed"),
					special = Pokemon.index(0, "special"),
					attackDV = attDV,
					defenseDV = defDV,
					speedDV = spdDV,
					specialDV = sclDV,
				}
				return Strategies.checkSquirtleStats(attack, defense, speed, special)
			else
				status.tries = status.tries + 1
			end
		end
		if Battle.isActive() and Battle.opponentAlive() then
			local attack = Memory.double("battle", "our_attack")
			if attack > 0 and RESET_FOR_TIME and not status.growled then
				if attack ~= status.attack then
					-- p(attack, Memory.double("battle", "opponent_hp"))
					status.attack = attack
				end
				local growled
				local attackBaseline = BEAST_MODE and 2 or 0
				if attack <= 2 + attackBaseline then
					growled = not Battle.opponentDamaged(3)
				elseif attack <= 3 + attackBaseline then
					growled = not Battle.opponentDamaged(1.9)
				end
				if growled then
					return Strategies.reset("time", "Growled to death", attack.." "..Memory.double("battle", "opponent_hp"))
				end
			end
			if Strategies.resetTime("bulbasaur", "beat Bulbasaur") then
				return true
			end
		end
		return Strategies.buffTo("tail_whip", 6)
	end,

	swapNidoran = function()
		local main = Memory.value("menu", "main")
		local nidoranIndex = Pokemon.indexOf("nidoran")
		if nidoranIndex == 0 then
			if Menu.close() then
				return true
			end
		elseif Menu.pause() then
			if Data.yellow then
				if Inventory.contains("potion") and Pokemon.info("nidoran", "hp") < 15 then
					Inventory.use("potion", "nidoran")
					return false
				end
			else
				if Combat.isPoisoned("squirtle") then
					Inventory.use("antidote", "squirtle")
					return false
				end
				if Inventory.contains("potion") and Pokemon.info("squirtle", "hp") < 15 then
					Inventory.use("potion", "squirtle")
					return false
				end
			end

			local column = Menu.getCol()
			if main == 128 then
				if column == 11 then
					Menu.select(1, true)
				elseif column == 12 then
					Menu.select(1, true)
				else
					Input.press("B")
				end
			elseif main == Menu.pokemon then
				local selectIndex
				if Memory.value("menu", "selection_mode") == 1 then
					selectIndex = nidoranIndex
				else
					selectIndex = 0
				end
				Pokemon.select(selectIndex)
			else
				Input.press("B")
			end
		end
	end,

	dodgePalletBoy = function()
		return Strategies.dodgeUp(0x0223, 14, 14, 15, 7)
	end,

	fightWeedle = function()
		if Strategies.trainerBattle() then
			if Memory.value("battle", "our_status") > 0 and not Inventory.contains("antidote") then
				return Strategies.reset("antidote", "Poisoned, but we skipped the antidote")
			end
			return Strategies.buffTo("tail_whip", 5)
		elseif status.foughtTrainer then
			return true
		end
	end,

	checkNidoranStats = function()
		local nidx = Pokemon.indexOf("nidoran")
		if Pokemon.index(nidx, "level") < 8 then
			return false
		end
		if not Data.yellow and status.tries < 300 then
			status.tries = status.tries + 1
			return false
		end

		local att = Pokemon.index(nidx, "attack")
		local def = Pokemon.index(nidx, "defense")
		local spd = Pokemon.index(nidx, "speed")
		local scl = Pokemon.index(nidx, "special")
		local attDV, defDV, spdDV, sclDV = Pokemon.getDVs("nidoran")
		local level4 = not Data.yellow and stats.nidoran.level4
		stats.nidoran = {
			attack = att,
			defense = def,
			speed = spd,
			special = scl,
			level4 = level4,
			rating = 0,
			attackDV = attDV,
			defenseDV = defDV,
			speedDV = spdDV,
			specialDV = sclDV,
		}

		local resetsForStats = att < 14 or spd < 13 or scl < 11
		local restrictiveStats = not Data.yellow and RESET_FOR_TIME
		if not resetsForStats and restrictiveStats then
			resetsForStats = att == 15 and spd == 14
		end

		if resetsForStats then
			local nidoranStatus = nil
			if att < 15 and spd < 14 and scl < 12 then
				--[[nidoranStatus = Utils.random {
					"let's just forget this ever happened",
					"I hate everything BibleThump ",
					"perfect stats Kappa ",
					"there's always the next one..",
					"worst possible stats hype",
					"unrunnable everything -.- "
				}--]]
			else
				if restrictiveStats and att == 15 and spd == 14 then
					nidoranStatus = Utils.append(nidoranStatus, "unrunnable attack/speed combination", ", ")
				else
					if att < 15 then
						nidoranStatus = Utils.append(nidoranStatus, "unrunnable attack", ", ")
					end
					if spd < 14 then
						nidoranStatus = Utils.append(nidoranStatus, "unrunnable speed", ", ")
					end
				end
				if scl < 12 then
					nidoranStatus = Utils.append(nidoranStatus, "unrunnable special", ", ")
				end
			end
			if not nidoranStatus then
				nidoranStatus = "unrunnable"
			end
			return Strategies.reset("stats", "Bad Nidoran - "..nidoranStatus)
		end
		status.tries = 9001

		local statDiff = (16 - att) + (15 - spd) + (13 - scl)
		if def < 12 then
			statDiff = statDiff + 1
		end
		if not Data.yellow and not stats.nidoran.level4 then
			statDiff = statDiff + 1
		end
		stats.nidoran.rating = statDiff

		local superlative
		local exclaim = "!"
		if statDiff == 0 then
			superlative = " perfect"
			exclaim = "! Kreygasm"
		elseif att == 16 and spd == 15 then
			if statDiff == 1 then
				superlative = " great"
			else
				superlative = " good"
			end
		elseif statDiff <= ((restrictiveStats or Data.yellow) and 3 or 4) then
			superlative = "n okay"
			exclaim = "."
		else
			superlative = " min stat"
			exclaim = "."
		end
		local message
		if Data.yellow then
			message = "caught"
		else
			message = "Beat Brock with"
		end
		message = message.." a"..superlative.." Nidoran"..exclaim

		if Data.yellow then
			message = message.." On "..(Strategies.vaporeon and "Vaporeon" or "Flareon").." strats."
		else
			message = message.." Caught at level "..(stats.nidoran.level4 and "4" or "3").."."
		end

		if BEAST_MODE then
			p("", true)
			p("", true)
		end
		--Bridge.chat(message)
		return true
	end,

	evolveNidorino = function()
		if Pokemon.inParty("nidorino") then
			Bridge.caught("nidorino")
			return true
		end
		if Battle.isActive() then
			status.tries = 0
			status.canProgress = true
			if not Battle.opponentAlive() then
				Input.press("A")
			else
				Battle.automate()
			end
		elseif status.tries > 3600 then
			print("Broke from Nidorino on tries")
			return true
		else
			if status.canProgress then
				status.tries = status.tries + 1
			end
			Input.press("A")
		end
	end,

	catchFlierBackup = function()
		if Strategies.initialize() then
			Bridge.guessing("moon", true)
			Control.canDie(true)
		end
		local caught = Pokemon.inParty("pidgey", "spearow")
		if Battle.isActive() then
			if Memory.double("battle", "our_hp") == 0 then
				local sacrifice = Pokemon.getSacrifice("squirtle", "pikachu")
				if not sacrifice then
					Control.canDie(false)
				elseif Menu.onPokemonSelect() then
					Pokemon.select(sacrifice)
				else
					Input.press("A")
				end
			else
				Battle.handle()
			end
		else
			local birdPath
			local px, py = Player.position()
			if caught then
				if px > 33 then
					return true
				end
				local startY = 9
				if px > 28 then
					startY = py
				end
				birdPath = {{32,startY}, {32,11}, {34,11}}
			elseif px == 37 then
				if not Control.canCatch() then
					return true
				end
				if py == 10 then
					py = 11
				else
					py = 10
				end
				Walk.step(px, py)
			else
				birdPath = {{32,10}, {32,11}, {34,11}, {34,10}, {37,10}}
			end
			if birdPath then
				Walk.custom(birdPath)
			end
		end
	end,

	evolveNidoking = function(data)
		if Battle.handleWild() then
			local usedMoonStone = not Inventory.contains("moon_stone")
			if Strategies.initialize() then
				if data.early then
					if not Control.getMoonExp then
						return true
					end
					if data.poke then
						if stats.nidoran.attack > 15 or not Pokemon.inParty(data.poke) then
							return true
						end
					end
					if data.exp and Pokemon.getExp() > data.exp then
						return true
					end
				end
			end
			if usedMoonStone then
				if Strategies.initialize("evolved") then
					Bridge.caught("nidoking")
				end
				if Strategies.closeMenuFor(data) then
					return true
				end
			elseif not Inventory.use("moon_stone") then
				Menu.pause()
				status.menuOpened = true
			end
		end
	end,

	fightGrimer = function()
		if Strategies.trainerBattle() then
			Battle.automate()
		elseif status.foughtTrainer then
			return true
		end
	end,

	helix = function()
		if Battle.handleWild() then
			if Inventory.contains("helix_fossil") then
				return true
			end
			Player.interact("Up", false)
		end
	end,

	reportMtMoon = function()
		local moonEncounters = Data.run.encounters_moon
		if moonEncounters then
			local cutterStatus
			local conjunction = "but"
			local goodEncounters = moonEncounters < 10

			local caughtCutter = Pokemon.inParty("paras", "sandshrew")
			local catchDescription
			local exclamation = "."
			if caughtCutter then
				catchDescription = caughtCutter
				if goodEncounters then
					conjunction = "and"
				end
				cutterStatus = "we caught a "..Utils.capitalize(caughtCutter)
				exclamation = "!"
			else
				local catchPokemon = Data.yellow and "sandshrew" or "paras"
				catchDescription = "no_"..catchPokemon
				if not goodEncounters then
					conjunction = "and"
				end
				cutterStatus = "we didn't catch a "
				if Data.yellow then
					cutterStatus = cutterStatus.."cutter"
				else
					cutterStatus = cutterStatus..Utils.capitalize(catchPokemon)
					exclamation = " :("
				end
			end
			Bridge.moonResults(moonEncounters, caughtCutter)
		end

		Strategies.resetTime("mt_moon", "complete Mt. Moon")
		return true
	end,

	dodgeCerulean = function(data)
		local left = data.left
		return dodgeSideways {
			npc = 0x0242,
			npcX = 15,
			sx = (left and 16 or 14), sy = 18,
			dodge = (left and 17 or 19),
			offset = 10,
			dist = (left and -7 or 4),
			left = left
		}
	end,

	rareCandyEarly = function(data)
		if Strategies.initialize() then
			if Pokemon.info("nidoking", "level") ~= 20 then
				status.cancel = true
			else
				if Pokemon.getExp() > 5550 then
					status.cancel = true
				else
					local encounterDescription = Data.yellow and "a Geodude" or "enough encounters"
				end
			end
		end
		data.poke = "nidoking"
		data.item = "rare_candy"
		data.all = true
		return strategyFunctions.item(data)
	end,

	teachThrash = function(data)
		if Strategies.initialize() then
			if Pokemon.info("nidoking", "level") ~= 21 or not Inventory.contains("rare_candy") then
				status.cancel = true
			else
				status.updateStats = true
			end
		end

		data.move = "thrash"
		data.poke = "nidoking"
		data.item = "rare_candy"
		data.replace = Data.yellow and "tackle" or "leer"
		data.all = true
		if strategyFunctions.teach(data) then
			if status.updateStats then
				nidokingStats()
			end
			return true
		end
	end,

	learnThrash = function()
		if Strategies.initialize() then
			if Pokemon.info("nidoking", "level") ~= 22 then
				return true
			end
		end
		if Strategies.trainerBattle() then
			if Pokemon.moveIndex("thrash", "nidoking") then
				nidokingStats()
				return true
			end
			local settingsRow = Memory.value("menu", "settings_row")
			if settingsRow == 8 then
				local column = Memory.value("menu", "column")
				if column == 15 then
					Input.press("A")
					return false
				end
				if column == 5 then
					local replacementMove = Data.yellow and "tackle" or "leer"
					local replaceIndex = Pokemon.moveIndex(replacementMove, "nidoking")
					if replaceIndex then
						Menu.select(replaceIndex - 1, true)
					else
						Input.cancel()
					end
					return false
				end
			end
			Battle.automate()
		elseif status.foughtTrainer then
			return true
		end
	end,

	swapThrash = function()
		if not Battle.isActive() then
			if Textbox.handle() and status.canProgress then
				return true
			end
		else
			status.canProgress = true
			return Battle.swapMove("thrash", 0)
		end
	end,

	lassEther = function()
		if Strategies.initialize() then
			if Data.yellow then
				if not Strategies.vaporeon or not Strategies.getsSilphCarbosSpecially() then
					return true
				end
				if Inventory.containsAll("pokeball", "potion") then
					return true
				end
			else
				if Inventory.containsAll("antidote", "elixer") then
					return true
				end
			end
		end
		return interact("Up")
	end,

	talkToBill = function()
		if Textbox.isActive() then
			return true
		end
		return interact("Up")
	end,

	potionBeforeMisty = function(data)
		if Strategies.initialize() then
			if data.goldeen then
				Strategies.setYolo("bills")
				if Control.yolo and Combat.hp() > 7 then
					return true
				end
			end
		end

		local healAmount = 72
		local canTwoHit = stats.nidoran.attackDV >= (Control.yolo and 8 or 9)
		local isSpeedTie = stats.nidoran.speedDV == 12
		local outspeeds = stats.nidoran.speedDV >= (Control.yolo and 12 or 13)
		if not Data.yellow and canTwoHit and outspeeds then
			healAmount = 46
		elseif canTwoHit and isSpeedTie then
			healAmount = 66
		elseif Control.yolo then
			healAmount = healAmount - 4
		end
		healAmount = healAmount - (stats.nidoran.special - 43)
		if Pokemon.index(0, "level") == 24 then
			healAmount = healAmount - 3
		end

		return strategyFunctions.potion({hp=healAmount, chain=data.chain})
	end,

	fightMisty = function()
		if Strategies.trainerBattle() then
			if Battle.redeployNidoking() then
				return false
			end
			--[[if Pokemon.isOpponent("staryu") then
				local __, turnsToKill = Combat.bestMove()
				if turnsToKill and turnsToKill > 1 then
					Strategies.chat("staryu", "needs a good damage range to 1-shot Staryu with this attack...")
				end
			end--]]

			if Battle.opponentAlive() and Combat.isConfused() then
				if not status.sacrifice and not Control.yolo and stats.nidoran.speedDV >= 11 then
					status.sacrifice = Pokemon.getSacrifice("pidgey", "spearow", "squirtle", "paras", "sandshrew", "charmander")
				end

				if Menu.onBattleSelect() then
					if Strategies.initialize("sacrificed") then
						local swapMessage = " Thrash didn't finish the kill :( "
						if Control.yolo then
							swapMessage = swapMessage.."Attempting to hit through Confusion to save time."
						elseif status.sacrifice then
							swapMessage = swapMessage.."Swapping out to cure Confusion."
						else
							swapMessage = swapMessage.."We'll have to hit through Confusion here."
						end
						--Bridge.chat(swapMessage)
					end
				end
				if status.sacrifice and Battle.sacrifice(status.sacrifice) then
					return false
				end
			end
			Battle.automate()
		elseif status.foughtTrainer then
			return true
		end
	end,

	announceMachop = function()
		if Strategies.trainerBattle() then
			Battle.automate()
		elseif status.foughtTrainer then
			return true
		end
	end,

	jingleSkip = function()
		if status.canProgress then
			local px, py = Player.position()
			if px < 4 then
				return true
			end
			Input.press("Left", 0)
		else
			Input.press("A", 2)
			status.canProgress = true
		end
	end,

	guess = function(data)
		Bridge.guessing(data.game, data.enabled)
		return true
	end,

	epicCutscene = function()
		return true
	end,

	fourTurnThrash = function()
		if Strategies.trainerBattle() then

			local forced
			if Pokemon.isOpponent("bellsprout") then
				if Battle.opponentAlive() then
					if Data.yellow and Combat.isConfused() and Combat.hp() < 25 then
						local potion = Inventory.contains("super_potion", "potion")
						if potion then
							Inventory.use(potion, nil, true)
							return false
						end
					end
					forced = "horn_attack"
				end
			end
			Battle.automate(forced)
		elseif status.foughtTrainer then
			return true
		end
	end,

	announceVenonat = function()
		if Strategies.trainerBattle() then
			if Pokemon.isOpponent("venonat") then
				local __, turnsToKill, turnsToDie = Combat.bestMove()
				if turnsToKill and turnsToKill > 1 and stats.nidoran.attackDV < 10 then
					local effectsDescription = turnsToDie == 1 and "kill/confuse" or "confuse"
					--Strategies.chat("range", "needs a good damage range to 1-shot this Venonat, which can "..effectsDescription.."...")
				end
			end
			Battle.automate()
		elseif status.foughtTrainer then
			return true
		end
	end,

	announceOddish = function()
		if Strategies.trainerBattle() then
			Battle.automate()
		elseif status.foughtTrainer then
			return true
		end
	end,

	healParalysis = function(data)
		if not Combat.isParalyzed() then
			return Strategies.closeMenuFor(data)
		end
		local heals = Inventory.contains("paralyze_heal", "full_restore")
		data.item = heals
		return Strategies.useItem(data)
	end,

	shopTM07 = function()
		return Shop.transaction {
			direction = "Up",
			buy = {{name="horn_drill", index=3}}
		}
	end,

	shopRepels = function()
		local repelCount = Data.yellow and 10 or 9
		return Shop.transaction {
			direction = "Up",
			buy = {{name="super_repel", index=3, amount=repelCount}}
		}
	end,

	shopPokeDoll = function()
		return Shop.transaction {
			direction = "Down",
			buy = {{name="pokedoll", index=0}}
		}
	end,

	shopVending = function()
		return Shop.vend {
			direction = "Up",
			buy = {{name="fresh_water", index=0}, {name="soda_pop", index=1}}
		}
	end,

	giveWater = function()
		if not Inventory.contains("fresh_water", "soda_pop") then
			return true
		end
		if Memory.value("menu", "shop_current") == 20 then
			Input.press("A")
		elseif Textbox.handle() then
			local cx, cy = Memory.raw(0x0223) - 3, Memory.raw(0x0222) - 3
			local px, py = Player.position()
			if Utils.dist(cx, cy, px, py) == 1 then
				Player.interact(Walk.dir(px, py, cx, cy))
			else
				Walk.step(cx, cy)
			end
		end
	end,

	shopExtraWater = function()
		return Shop.vend {
			direction = "Up",
			buy = {{name="fresh_water", index=0}}
		}
	end,

	digFight = function()
		if Strategies.initialize() then
			if Combat.inRedBar() then
				--Bridge.chat("is using Rock Slide to one-hit these Ghastlies in red-bar (each is 1 in 10 to miss).")
			end
		end
		if Strategies.trainerBattle() then
			local currentlyDead = Memory.double("battle", "our_hp") == 0
			if currentlyDead then
				local backupPokemon = Pokemon.getSacrifice("paras", "squirtle", "sandshrew", "charmander")
				if not backupPokemon then
					return Strategies.death()
				end

				if Menu.onPokemonSelect() then
					Pokemon.select(backupPokemon)
				else
					Input.press("A")
				end
			else
				Battle.automate()
			end
		elseif status.foughtTrainer then
			return true
		end
	end,

	pokeDoll = function()
		if Battle.isActive() then
			status.canProgress = true
			-- {s="swap",item="potion",dest="x_special",chain=true}, --TODO yellow
			Inventory.use("pokedoll", nil, true)
		elseif status.canProgress then
			return true
		else
			Input.cancel()
		end
	end,

	silphElevator = function()
		if Menu.isOpened() then
			status.canProgress = true
			Menu.select(9, false, true)
		else
			if status.canProgress then
				return true
			end
			Player.interact("Up")
		end
	end,

	silphCarbos = function()
		if Strategies.initialize() then
			local getCarbos = Strategies.needsCarbosAtLeast(2)
			if getCarbos then
				if not Data.yellow then
					--Bridge.chat(" This Nidoking has bad speed, so we need the extra Carbos here.")
				end
			elseif Strategies.getsSilphCarbosSpecially() then
				getCarbos = true
			end
			if not getCarbos then
				return true
			end
		end
		return strategyFunctions.interact({dir="Left"})
	end,

	playPokeFlute = function()
		if Battle.isActive() then
			return true
		end
		if Menu.hasTextbox() then
			Input.cancel()
		elseif Menu.pause() then
			Inventory.use("pokeflute")
		end
	end,

	push = function(data)
		local pos
		if data.dir == "Up" or data.dir == "Down" then
			pos = data.y
		else
			pos = data.x
		end
		local newP = Memory.raw(pos)
		if not status.startPosition then
			status.startPosition = newP
		elseif status.startPosition ~= newP then
			return true
		end
		Input.press(data.dir, 0)
	end,

	drivebyRareCandy = function()
		if Textbox.isActive() then
			status.canProgress = true
			Input.cancel()
		elseif status.canProgress then
			return true
		else
			local px, py = Player.position()
			if py < 13 then
				status.tries = 0
				return
			end
			if py == 13 and status.tries % 2 == 0 then
				Input.press("A", 2)
			else
				Input.press("Up")
				status.tries = 0
			end
			status.tries = status.tries + 1
		end
	end,

	safariCarbos = function()
		if Strategies.initialize() then
			Strategies.setYolo("safari_carbos")
			status.carbos = Inventory.count("carbos")

			if not Strategies.needsCarbosAtLeast(3) then
				return true
			end

		end
		if Inventory.count("carbos") ~= status.carbos then
			if Walk.step(20, 20) then
				return true
			end
		else
			local px, py = Player.position()
			if px < 21 then
				Walk.step(21, py)
			elseif px == 21 and py == 13 then
				Player.interact("Left")
			else
				Walk.step(21, 13)
			end
		end
	end,

	tossInSafari = function()
		if Inventory.count() <= (Inventory.contains("full_restore") and 18 or 17) then
			return Strategies.closeMenuFor({close=true})
		end
		if Data.red and Inventory.contains("carbos") then
			strategyFunctions.item({item="carbos",poke="nidoking",all=true})
			return false
		end
		return Strategies.tossItem("antidote", "tm34", "pokeball")
	end,

	extraFullRestore = function()
		if Strategies.initialize() then
			if not Data.yellow then
				if Control.yolo or Inventory.contains("full_restore") then
					return true
				end

			end
		end
		local px, py = Player.position()
		if px < 21 then
			px = 21
		elseif py < 9 then
			py = 9
		else
			return strategyFunctions.interact({dir="Down"})
		end
		Walk.step(px, py)
	end,

	dodgeGirl = function()
		local gx, gy = Memory.raw(0x0223) - 5, Memory.raw(0x0222)
		local px, py = Player.position()
		if py > gy then
			if px > 3 then
				px = 3
			else
				return true
			end
		elseif gy - py ~= 1 or px ~= gx then
			py = py + 1
		elseif px == 3 then
			px = 2
		else
			px = 3
		end
		Walk.step(px, py)
	end,

	cinnabarCarbos = function()
		local skipsCarbos = not Strategies.needsCarbosAtLeast(Data.yellow and 2 or 1)
		if Strategies.initialize() then
			status.startCount = Inventory.count("carbos")
		end

		local px, py = Player.position()
		if px == 21 then
			return true
		end
		if skipsCarbos then
			px, py = 21, 20
		else
			if py == 20 then
				py = 21
			elseif px == 17 and Inventory.count("carbos") == status.startCount then
				Player.interact("Right")
				return false
			else
				px = 21
			end
		end
		Walk.step(px, py)
	end,

	ether = function(data)
		data.item = status.item
		if status.item and Strategies.completedMenuFor(data) then
			if Strategies.closeMenuFor(data) then
				return true
			end
		else
			if not status.item then
				if data.max then
					if not useEtherInsteadOfCenter() then
						return true
					end
				end

				status.item = Inventory.contains("ether", "max_ether", "elixer")
				if not status.item then
					if Strategies.closeMenuFor(data) then
						return true
					end
					print("No Ether - "..Control.areaName)
					return false
				end
			end
			if status.item == "elixer" then
				data.item = "elixer"
				data.poke = "nidoking"
				return Strategies.useItem(data)
			end
			if Memory.value("menu", "main") == 144 and Menu.getCol() == 5 then
				if Menu.hasTextbox() then
					Input.cancel()
				else
					Menu.select(Pokemon.battleMove("horn_drill"), true)
				end
			elseif Menu.pause() then
				Inventory.use(status.item, "nidoking")
				status.menuOpened = true
			end
		end
	end,

	tossInVictoryRoad = function()
		if Strategies.initialize() then
			if not requiresMaxEther() or not Inventory.isFull() or Inventory.contains("max_ether") then
				return true
			end
		end
		return Strategies.tossItem("antidote", "tm34", "x_attack", "pokeball")
	end,

	grabMaxEther = function()
		if Strategies.initialize() then
			if Inventory.isFull() or not requiresMaxEther() then
				return true
			end
			status.startCount = Inventory.count("max_ether")
		end

		if Inventory.count("max_ether") > status.startCount then
			return true
		end
		local px, py = Player.position()
		if px > 7 then
			return Strategies.reset("error", "Accidentally walked on the island :(", px, true)
		end
		if Memory.value("player", "moving") == 0 then
			Player.interact("Right")
		end
	end,

	potionBeforeLorelei = function(data)
		if Strategies.initialize() then
			if Strategies.requiresE4Center(true, true) then
				return true
			end
			if not Strategies.canHealFor("LoreleiDewgong") then
				return true
			end
		end

		data.hp = Combat.healthFor("LoreleiDewgong")
		return strategyFunctions.potion(data)
	end,

	centerSkip = function()
		if Strategies.initialize() then
			Strategies.setYolo("e4center")

			--Bridge.chat("is taking the Center to heal HP/PP for Lorelei.")
		end
		return strategyFunctions.dialogue({dir="Up"})
	end,

	prepareForLance = function()
		local curr_hp = Combat.hp()
		local min_recovery = Combat.healthFor("LanceGyarados")
		if not Control.yolo then
			min_recovery = min_recovery + 1
		end

		local enableFull = Inventory.count("full_restore") > (Control.yolo and 0 or 1)
		if curr_hp + 50 < min_recovery then
			enableFull = not Inventory.contains("super_potion")
		elseif curr_hp + 100 < min_recovery then
			enableFull = Inventory.count("super_potion") < 2
		end
		return strategyFunctions.potion({hp=min_recovery, full=enableFull, chain=true})
	end,

	champion = function()
		if status.finishTime then
			if not status.frames then
				status.frames = 0
				local victoryMessage = "Beat Pokemon "..Utils.capitalize(Data.gameName).." in "..status.finishTime
				--if not Strategies.overMinute("champion") then
				--	victoryMessage = victoryMessage..", a new PB!"
				--end
				Strategies.tweetProgress(victoryMessage)
				if Data.run.seed then
					Data.setFrames()
					print("v"..VERSION..": "..Data.run.frames.." frames, with seed "..Data.run.seed)

					if (Data.yellow or not INTERNAL or RESET_FOR_TIME) then
						gui.cleartext()
						gui.text(0, 0, "PokeBot v"..VERSION)
						gui.text(0, 21, "Seed: "..Data.run.seed)
						gui.text(0, 42, "Name: ADAM")
						gui.text(0, 63, "Time: "..Utils.elapsedTime())
						client.setscreenshotosd(true)
						client.screenshot()
						client.setscreenshotosd(false)
						gui.cleartext()
					end
				end
				Bridge.guessResults("elite4", "victory")
			elseif status.frames > 1800 then
				return Strategies.hardReset("won", "Finished the game in "..status.finishTime)
			end
			status.frames = status.frames + 1
		elseif Memory.value("menu", "shop_current") == 252 then
			strategyFunctions.split({finished=true})
			status.finishTime = Utils.elapsedTime()
		else
			Input.cancel()
		end
	end,

}

strategyFunctions = Strategies.functions

function Strategies.execute(data)
	local strategyFunction = strategyFunctions[data.s]
	if not strategyFunction then
		return true
	end
	if strategyFunction(data) then
		status = {tries=0}
		Strategies.status = status
		Strategies.completeGameStrategy()

		if resetting then
			return nil
		end
		return true
	end
	return false
end

function Strategies.init(midGame)
	splitTime = Utils.timeSince(0)
	if midGame then
		Control.preferredPotion = "super"
		Combat.factorPP(true)
	end

	local nido = Pokemon.inParty("nidoran", "nidorino", "nidoking")
	if nido then
		local attDV, defDV, spdDV, sclDV = Pokemon.getDVs(nido)
		p(attDV, defDV, spdDV, sclDV)
		stats.nidoran = {
			rating = 1,
			attackDV = attDV,
			defenseDV = defDV,
			speedDV = spdDV,
			specialDV = sclDV,
			level4 = true,
		}
		if nido == "nidoking" then
			stats.nidoran.attack = 55
			stats.nidoran.defense = 45
			stats.nidoran.speed = 50
			stats.nidoran.special = 45
		else
			stats.nidoran.attack = 16
			stats.nidoran.defense = 12
			stats.nidoran.speed = 15
			stats.nidoran.special = 13
		end
		--p(stats.nidoran.attack, "x", stats.nidoran.speed, stats.nidoran.special)
	end

	Strategies.initGame(midGame)
end

function Strategies.softReset()
	--status = {tries=0}
	status = {tries = 0, canProgress = nil, initialized = false}

	Strategies.status = status
	stats = {}
	Strategies.stats = stats
	Strategies.updates = {}

	splitNumber, splitTime = 0, 0
	resetting = nil
	Strategies.deepRun = false
	Strategies.resetGame()
end

return Strategies

redpajama_set_name: RedPajamaGithub


text:
#ifndef CIVETWEB_HEADER_INCLUDED
#define CIVETWEB_HEADER_INCLUDED

#define CIVETWEB_VERSION "1.8"

#ifndef CIVETWEB_API
#if defined(_WIN32)
#if defined(CIVETWEB_DLL_EXPORTS)
#define CIVETWEB_API __declspec(dllexport)
#elif defined(CIVETWEB_DLL_IMPORTS)
#define CIVETWEB_API __declspec(dllimport)
#else
#define CIVETWEB_API
#endif
#elif __GNUC__ >= 4
#define CIVETWEB_API __attribute__((visibility("default")))
#else
#define CIVETWEB_API
#endif
#endif

#include <stdio.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

struct mg_context;    /* Handle for the HTTP service itself */
struct mg_connection; /* Handle for the individual connection */

/* This structure contains information about the HTTP request. */
struct mg_request_info {
	const char *request_method; /* "GET", "POST", etc */
	const char *uri;            /* URL-decoded URI */
	const char *http_version;   /* E.g. "1.0", "1.1" */
	const char *query_string;   /* URL part after '?', not including '?', or
	                               NULL */
	const char *remote_user;    /* Authenticated user, or NULL if no auth
	                               used */
	char remote_addr[48];       /* Client's IP address as a string. */

#if defined(MG_LEGACY_INTERFACE)
	long remote_ip; /* Client's IP address. Deprecated: use remote_addr instead
	                   */
#endif

	long long content_length; /* Length (in bytes) of the request body,
	                             can be -1 if no length was given. */
	int remote_port;          /* Client's port */
	int is_ssl;               /* 1 if SSL-ed, 0 if not */
	void *user_data;          /* User data pointer passed to mg_start() */
	void *conn_data;          /* Connection-specific user data */

	int num_headers; /* Number of HTTP headers */
	struct mg_header {
		const char *name;  /* HTTP header name */
		const char *value; /* HTTP header value */
	} http_headers[64];    /* Maximum 64 headers */
};

/* This structure needs to be passed to mg_start(), to let civetweb know
   which callbacks to invoke. For a detailed description, see
   https://github.com/civetweb/civetweb/blob/master/docs/UserManual.md */
struct mg_callbacks {
	/* Called when civetweb has received new HTTP request.
	   If the callback returns one, it must process the request
	   by sending valid HTTP headers and a body. Civetweb will not do
	   any further processing. Otherwise it must return zero.
	   Note that since V1.7 the "begin_request" function is called
	   before an authorization check. If an authorization check is
	   required, use a request_handler instead.
	   Return value:
	     0: civetweb will process the request itself. In this case,
	        the callback must not send any data to the client.
	     1-999: callback already processed the request. Civetweb will
	            not send any data after the callback returned. The
	            return code is stored as a HTTP status code for the
	            access log. */
	int (*begin_request)(struct mg_connection *);

	/* Called when civetweb has finished processing request. */
	void (*end_request)(const struct mg_connection *, int reply_status_code);

	/* Called when civetweb is about to log a message. If callback returns
	   non-zero, civetweb does not log anything. */
	int (*log_message)(const struct mg_connection *, const char *message);

	/* Called when civetweb is about to log access. If callback returns
	   non-zero, civetweb does not log anything. */
	int (*log_access)(const struct mg_connection *, const char *message);

	/* Called when civetweb initializes SSL library.
	   Parameters:
	     user_data: parameter user_data passed when starting the server.
	   Return value:
	     0: civetweb will set up the SSL certificate.
	     1: civetweb assumes the callback already set up the certificate.
	    -1: initializing ssl fails. */
	int (*init_ssl)(void *ssl_context, void *user_data);

#if defined(MG_LEGACY_INTERFACE)
	/* Called when websocket request is received, before websocket handshake.
	   Return value:
	     0: civetweb proceeds with websocket handshake.
	     1: connection is closed immediately.
	   This callback is deprecated, use mg_set_websocket_handler instead. */
	int (*websocket_connect)(const struct mg_connection *);

	/* Called when websocket handshake is successfully completed, and
	   connection is ready for data exchange.
	   This callback is deprecated, use mg_set_websocket_handler instead. */
	void (*websocket_ready)(struct mg_connection *);

	/* Called when data frame has been received from the client.
	   Parameters:
	     bits: first byte of the websocket frame, see websocket RFC at
	           http://tools.ietf.org/html/rfc6455, section 5.2
	     data, data_len: payload, with mask (if any) already applied.
	   Return value:
	     1: keep this websocket connection open.
	     0: close this websocket connection.
	   This callback is deprecated, use mg_set_websocket_handler instead. */
	int (*websocket_data)(struct mg_connection *,
	                      int bits,
	                      char *data,
	                      size_t data_len);
#endif /* MG_LEGACY_INTERFACE */

	/* Called when civetweb is closing a connection.  The per-context mutex is
	   locked when this is invoked.  This is primarily useful for noting when
	   a websocket is closing and removing it from any application-maintained
	   list of clients.
	   Using this callback for websocket connections is deprecated, use
	   mg_set_websocket_handler instead. */
	void (*connection_close)(const struct mg_connection *);

	/* Called when civetweb tries to open a file. Used to intercept file open
	   calls, and serve file data from memory instead.
	   Parameters:
	      path:     Full path to the file to open.
	      data_len: Placeholder for the file size, if file is served from
	                memory.
	   Return value:
	     NULL: do not serve file from memory, proceed with normal file open.
	     non-NULL: pointer to the file contents in memory. data_len must be
	       initilized with the size of the memory block. */
	const char *(*open_file)(const struct mg_connection *,
	                         const char *path,
	                         size_t *data_len);

	/* Called when civetweb is about to serve Lua server page, if
	   Lua support is enabled.
	   Parameters:
	     lua_context: "lua_State *" pointer. */
	void (*init_lua)(const struct mg_connection *, void *lua_context);

	/* Called when civetweb has uploaded a file to a temporary directory as a
	   result of mg_upload() call.
	   Parameters:
	     file_name: full path name to the uploaded file. */
	void (*upload)(struct mg_connection *, const char *file_name);

	/* Called when civetweb is about to send HTTP error to the client.
	   Implementing this callback allows to create custom error pages.
	   Parameters:
	     status: HTTP error status code.
	   Return value:
	     1: run civetweb error handler.
	     0: callback already handled the error. */
	int (*http_error)(struct mg_connection *, int status);

	/* Called after civetweb context has been created, before requests
	   are processed.
	   Parameters:
	     ctx: context handle */
	void (*init_context)(const struct mg_context *ctx);

	/* Called when civetweb context is deleted.
	   Parameters:
	     ctx: context handle */
	void (*exit_context)(const struct mg_context *ctx);
};

/* Start web server.

   Parameters:
     callbacks: mg_callbacks structure with user-defined callbacks.
     options: NULL terminated list of option_name, option_value pairs that
              specify Civetweb configuration parameters.

   Side-effects: on UNIX, ignores SIGCHLD and SIGPIPE signals. If custom
      processing is required for these, signal handlers must be set up
      after calling mg_start().

   Example:
     const char *options[] = {
       "document_root", "/var/www",
       "listening_ports", "80,443s",
       NULL
     };
     struct mg_context *ctx = mg_start(&my_func, NULL, options);

   Refer to https://github.com/civetweb/civetweb/blob/master/docs/UserManual.md
   for the list of valid option and their possible values.

   Return:
     web server context, or NULL on error. */
CIVETWEB_API struct mg_context *mg_start(const struct mg_callbacks *callbacks,
                                         void *user_data,
                                         const char **configuration_options);

/* Stop the web server.

   Must be called last, when an application wants to stop the web server and
   release all associated resources. This function blocks until all Civetweb
   threads are stopped. Context pointer becomes invalid. */
CIVETWEB_API void mg_stop(struct mg_context *);

/* mg_request_handler

   Called when a new request comes in.  This callback is URI based
   and configured with mg_set_request_handler().

   Parameters:
      conn: current connection information.
      cbdata: the callback data configured with mg_set_request_handler().
   Returns:
      0: the handler could not handle the request, so fall through.
      1 - 999: the handler processed the request. The return code is
               stored as a HTTP status code for the access log. */
typedef int (*mg_request_handler)(struct mg_connection *conn, void *cbdata);

/* mg_set_request_handler

   Sets or removes a URI mapping for a request handler.
   This function uses mg_lock_context internally.

   URI's are ordered and prefixed URI's are supported. For example,
   consider two URIs: /a/b and /a
           /a   matches /a
           /a/b matches /a/b
           /a/c matches /a

   Parameters:
      ctx: server context
      uri: the URI (exact or pattern) for the handler
      handler: the callback handler to use when the URI is requested.
               If NULL, an already registered handler for this URI will be
   removed.
               The URI used to remove a handler must match exactly the one used
   to
               register it (not only a pattern match).
      cbdata: the callback data to give to the handler when it is called. */
CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx,
                                         const char *uri,
                                         mg_request_handler handler,
                                         void *cbdata);

/* Callback types for websocket handlers in C/C++.

   mg_websocket_connect_handler
       Is called when the client intends to establish a websocket connection,
       before websocket handshake.
       Return value:
         0: civetweb proceeds with websocket handshake.
         1: connection is closed immediately.

   mg_websocket_ready_handler
       Is called when websocket handshake is successfully completed, and
       connection is ready for data exchange.

   mg_websocket_data_handler
       Is called when a data frame has been received from the client.
       Parameters:
         bits: first byte of the websocket frame, see websocket RFC at
               http://tools.ietf.org/html/rfc6455, section 5.2
         data, data_len: payload, with mask (if any) already applied.
       Return value:
         1: keep this websocket connection open.
         0: close this websocket connection.

   mg_connection_close_handler
       Is called, when the connection is closed.*/
typedef int (*mg_websocket_connect_handler)(const struct mg_connection *,
                                            void *);
typedef void (*mg_websocket_ready_handler)(struct mg_connection *, void *);
typedef int (*mg_websocket_data_handler)(
    struct mg_connection *, int, char *, size_t, void *);
typedef void (*mg_websocket_close_handler)(const struct mg_connection *,
                                           void *);

/* mg_set_websocket_handler

   Set or remove handler functions for websocket connections.
   This function works similar to mg_set_request_handler - see there. */
CIVETWEB_API void
mg_set_websocket_handler(struct mg_context *ctx,
                         const char *uri,
                         mg_websocket_connect_handler connect_handler,
                         mg_websocket_ready_handler ready_handler,
                         mg_websocket_data_handler data_handler,
                         mg_websocket_close_handler close_handler,
                         void *cbdata);

/* Get the value of particular configuration parameter.
   The value returned is read-only. Civetweb does not allow changing
   configuration at run time.
   If given parameter name is not valid, NULL is returned. For valid
   names, return value is guaranteed to be non-NULL. If parameter is not
   set, zero-length string is returned. */
CIVETWEB_API const char *mg_get_option(const struct mg_context *ctx,
                                       const char *name);

/* Get context from connection. */
CIVETWEB_API struct mg_context *
mg_get_context(const struct mg_connection *conn);

/* Get user data passed to mg_start from context. */
CIVETWEB_API void *mg_get_user_data(const struct mg_context *ctx);

/* Set user data for the current connection. */
CIVETWEB_API void mg_set_user_connection_data(const struct mg_connection *conn,
                                              void *data);

/* Get user data set for the current connection. */
CIVETWEB_API void *
mg_get_user_connection_data(const struct mg_connection *conn);

#if defined(MG_LEGACY_INTERFACE)
/* Return array of strings that represent valid configuration options.
   For each option, option name and default value is returned, i.e. the
   number of entries in the array equals to number_of_options x 2.
   Array is NULL terminated. */
/* Deprecated: Use mg_get_valid_options instead. */
CIVETWEB_API const char **mg_get_valid_option_names(void);
#endif

struct mg_option {
	const char *name;
	int type;
	const char *default_value;
};

enum {
	CONFIG_TYPE_UNKNOWN = 0x0,
	CONFIG_TYPE_NUMBER = 0x1,
	CONFIG_TYPE_STRING = 0x2,
	CONFIG_TYPE_FILE = 0x3,
	CONFIG_TYPE_DIRECTORY = 0x4,
	CONFIG_TYPE_BOOLEAN = 0x5,
	CONFIG_TYPE_EXT_PATTERN = 0x6
};

/* Return array of struct mg_option, representing all valid configuration
   options of civetweb.c.
   The array is terminated by a NULL name option. */
CIVETWEB_API const struct mg_option *mg_get_valid_options(void);

/* Get the list of ports that civetweb is listening on.
   size is the size of the ports int array and ssl int array to fill.
   It is the caller's responsibility to make sure ports and ssl each
   contain at least size int elements worth of memory to write into.
   Return value is the number of ports and ssl information filled in.
   The value returned is read-only. Civetweb does not allow changing
   configuration at run time. */
CIVETWEB_API size_t
mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl);

/* Add, edit or delete the entry in the passwords file.

   This function allows an application to manipulate .htpasswd files on the
   fly by adding, deleting and changing user records. This is one of the
   several ways of implementing authentication on the server side. For another,
   cookie-based way please refer to the examples/chat in the source tree.

   If password is not NULL, entry is added (or modified if already exists).
   If password is NULL, entry is deleted.

   Return:
     1 on success, 0 on error. */
CIVETWEB_API int mg_modify_passwords_file(const char *passwords_file_name,
                                          const char *domain,
                                          const char *user,
                                          const char *password);

/* Return information associated with the request. */
CIVETWEB_API const struct mg_request_info *
mg_get_request_info(const struct mg_connection *);

/* Send data to the client.
   Return:
    0   when the connection has been closed
    -1  on error
    >0  number of bytes written on success */
CIVETWEB_API int mg_write(struct mg_connection *, const void *buf, size_t len);

/* Send data to a websocket client wrapped in a websocket frame.  Uses
   mg_lock_connection to ensure that the transmission is not interrupted,
   i.e., when the application is proactively communicating and responding to
   a request simultaneously.

   Send data to a websocket client wrapped in a websocket frame.
   This function is available when civetweb is compiled with -DUSE_WEBSOCKET

   Return:
    0   when the connection has been closed
    -1  on error
    >0  number of bytes written on success */
CIVETWEB_API int mg_websocket_write(struct mg_connection *conn,
                                    int opcode,
                                    const char *data,
                                    size_t data_len);

/* Blocks until unique access is obtained to this connection. Intended for use
   with websockets only.
   Invoke this before mg_write or mg_printf when communicating with a
   websocket if your code has server-initiated communication as well as
   communication in direct response to a message. */
CIVETWEB_API void mg_lock_connection(struct mg_connection *conn);
CIVETWEB_API void mg_unlock_connection(struct mg_connection *conn);

#if defined(MG_LEGACY_INTERFACE)
#define mg_lock mg_lock_connection
#define mg_unlock mg_unlock_connection
#endif

/* Lock server context.  This lock may be used to protect resources
   that are shared between different connection/worker threads. */
CIVETWEB_API void mg_lock_context(struct mg_context *ctx);
CIVETWEB_API void mg_unlock_context(struct mg_context *ctx);

/* Opcodes, from http://tools.ietf.org/html/rfc6455 */
enum {
	WEBSOCKET_OPCODE_CONTINUATION = 0x0,
	WEBSOCKET_OPCODE_TEXT = 0x1,
	WEBSOCKET_OPCODE_BINARY = 0x2,
	WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
	WEBSOCKET_OPCODE_PING = 0x9,
	WEBSOCKET_OPCODE_PONG = 0xa
};

/* Macros for enabling compiler-specific checks for printf-like arguments. */
#undef PRINTF_FORMAT_STRING
#if defined(_MSC_VER) && _MSC_VER >= 1400
#include <sal.h>
#if defined(_MSC_VER) && _MSC_VER > 1400
#define PRINTF_FORMAT_STRING(s) _Printf_format_string_ s
#else
#define PRINTF_FORMAT_STRING(s) __format_string s
#endif
#else
#define PRINTF_FORMAT_STRING(s) s
#endif

#ifdef __GNUC__
#define PRINTF_ARGS(x, y) __attribute__((format(printf, x, y)))
#else
#define PRINTF_ARGS(x, y)
#endif

/* Send data to the client using printf() semantics.
   Works exactly like mg_write(), but allows to do message formatting. */
CIVETWEB_API int mg_printf(struct mg_connection *,
                           PRINTF_FORMAT_STRING(const char *fmt),
                           ...) PRINTF_ARGS(2, 3);

/* Send contents of the entire file together with HTTP headers. */
CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path);

/* Read data from the remote end, return number of bytes read.
   Return:
     0     connection has been closed by peer. No more data could be read.
     < 0   read error. No more data could be read from the connection.
     > 0   number of bytes read into the buffer. */
CIVETWEB_API int mg_read(struct mg_connection *, void *buf, size_t len);

/* Get the value of particular HTTP header.

   This is a helper function. It traverses request_info->http_headers array,
   and if the header is present in the array, returns its value. If it is
   not present, NULL is returned. */
CIVETWEB_API const char *mg_get_header(const struct mg_connection *,
                                       const char *name);

/* Get a value of particular form variable.

   Parameters:
     data: pointer to form-uri-encoded buffer. This could be either POST data,
           or request_info.query_string.
     data_len: length of the encoded data.
     var_name: variable name to decode from the buffer
     dst: destination buffer for the decoded variable
     dst_len: length of the destination buffer

   Return:
     On success, length of the decoded variable.
     On error:
        -1 (variable not found).
        -2 (destination buffer is NULL, zero length or too small to hold the
            decoded variable).

   Destination buffer is guaranteed to be '\0' - terminated if it is not
   NULL or zero length. */
CIVETWEB_API int mg_get_var(const char *data,
                            size_t data_len,
                            const char *var_name,
                            char *dst,
                            size_t dst_len);

/* Get a value of particular form variable.

   Parameters:
     data: pointer to form-uri-encoded buffer. This could be either POST data,
           or request_info.query_string.
     data_len: length of the encoded data.
     var_name: variable name to decode from the buffer
     dst: destination buffer for the decoded variable
     dst_len: length of the destination buffer
     occurrence: which occurrence of the variable, 0 is the first, 1 the
                 second...
                this makes it possible to parse a query like
                b=x&a=y&a=z which will have occurrence values b:0, a:0 and a:1

   Return:
     On success, length of the decoded variable.
     On error:
        -1 (variable not found).
        -2 (destination buffer is NULL, zero length or too small to hold the
            decoded variable).

   Destination buffer is guaranteed to be '\0' - terminated if it is not
   NULL or zero length. */
CIVETWEB_API int mg_get_var2(const char *data,
                             size_t data_len,
                             const char *var_name,
                             char *dst,
                             size_t dst_len,
                             size_t occurrence);

/* Fetch value of certain cookie variable into the destination buffer.

   Destination buffer is guaranteed to be '\0' - terminated. In case of
   failure, dst[0] == '\0'. Note that RFC allows many occurrences of the same
   parameter. This function returns only first occurrence.

   Return:
     On success, value length.
     On error:
        -1 (either "Cookie:" header is not present at all or the requested
            parameter is not found).
        -2 (destination buffer is NULL, zero length or too small to hold the
            value). */
CIVETWEB_API int mg_get_cookie(const char *cookie,
                               const char *var_name,
                               char *buf,
                               size_t buf_len);

/* Download data from the remote web server.
     host: host name to connect to, e.g. "foo.com", or "10.12.40.1".
     port: port number, e.g. 80.
     use_ssl: wether to use SSL connection.
     error_buffer, error_buffer_size: error message placeholder.
     request_fmt,...: HTTP request.
   Return:
     On success, valid pointer to the new connection, suitable for mg_read().
     On error, NULL. error_buffer contains error message.
   Example:
     char ebuf[100];
     struct mg_connection *conn;
     conn = mg_download("google.com", 80, 0, ebuf, sizeof(ebuf),
                        "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
 */
CIVETWEB_API struct mg_connection *
mg_download(const char *host,
            int port,
            int use_ssl,
            char *error_buffer,
            size_t error_buffer_size,
            PRINTF_FORMAT_STRING(const char *request_fmt),
            ...) PRINTF_ARGS(6, 7);

/* Close the connection opened by mg_download(). */
CIVETWEB_API void mg_close_connection(struct mg_connection *conn);

/* File upload functionality. Each uploaded file gets saved into a temporary
   file and MG_UPLOAD event is sent.
   Return number of uploaded files. */
CIVETWEB_API int mg_upload(struct mg_connection *conn,
                           const char *destination_dir);

/* Convenience function -- create detached thread.
   Return: 0 on success, non-0 on error. */
typedef void *(*mg_thread_func_t)(void *);
CIVETWEB_API int mg_start_thread(mg_thread_func_t f, void *p);

/* Return builtin mime type for the given file name.
   For unrecognized extensions, "text/plain" is returned. */
CIVETWEB_API const char *mg_get_builtin_mime_type(const char *file_name);

/* Return Civetweb version. */
CIVETWEB_API const char *mg_version(void);

/* URL-decode input buffer into destination buffer.
   0-terminate the destination buffer.
   form-url-encoded data differs from URI encoding in a way that it
   uses '+' as character for space, see RFC 1866 section 8.2.1
   http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
   Return: length of the decoded data, or -1 if dst buffer is too small. */
CIVETWEB_API int mg_url_decode(const char *src,
                               int src_len,
                               char *dst,
                               int dst_len,
                               int is_form_url_encoded);

/* URL-encode input buffer into destination buffer.
   returns the length of the resulting buffer or -1
   is the buffer is too small. */
CIVETWEB_API int mg_url_encode(const char *src, char *dst, size_t dst_len);

/* MD5 hash given strings.
   Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of
   ASCIIz strings. When function returns, buf will contain human-readable
   MD5 hash. Example:
     char buf[33];
     mg_md5(buf, "aa", "bb", NULL); */
CIVETWEB_API char *mg_md5(char buf[33], ...);

/* Print error message to the opened error log stream.
   This utilizes the provided logging configuration.
     conn: connection
     fmt: format string without the line return
     ...: variable argument list
   Example:
     mg_cry(conn,"i like %s", "logging"); */
CIVETWEB_API void mg_cry(const struct mg_connection *conn,
                         PRINTF_FORMAT_STRING(const char *fmt),
                         ...) PRINTF_ARGS(2, 3);

/* utility method to compare two buffers, case incensitive. */
CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len);

/* Connect to a websocket as a client
   Parameters:
     host: host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or
   "localhost"
     port: server port
     use_ssl: make a secure connection to server
     error_buffer, error_buffer_size: buffer for an error message
     path: server path you are trying to connect to, i.e. if connection to
   localhost/app, path should be "/app"
     origin: value of the Origin HTTP header
     data_func: callback that should be used when data is received from the
   server
     user_data: user supplied argument

   Return:
     On success, valid mg_connection object.
     On error, NULL. Se error_buffer for details.
*/

CIVETWEB_API struct mg_connection *
mg_connect_websocket_client(const char *host,
                            int port,
                            int use_ssl,
                            char *error_buffer,
                            size_t error_buffer_size,
                            const char *path,
                            const char *origin,
                            mg_websocket_data_handler data_func,
                            mg_websocket_close_handler close_func,
                            void *user_data);

/* Connect to a TCP server as a client (can be used to connect to a HTTP server)
   Parameters:
     host: host to connect to, i.e. "www.wikipedia.org" or "192.168.1.1" or
   "localhost"
     port: server port
     use_ssl: make a secure connection to server
     error_buffer, error_buffer_size: buffer for an error message

   Return:
     On success, valid mg_connection object.
     On error, NULL. Se error_buffer for details.
*/
CIVETWEB_API struct mg_connection *mg_connect_client(const char *host,
                                                     int port,
                                                     int use_ssl,
                                                     char *error_buffer,
                                                     size_t error_buffer_size);

enum { TIMEOUT_INFINITE = -1 };

/* Wait for a response from the server
   Parameters:
     conn: connection
     ebuf, ebuf_len: error message placeholder.
     timeout: time to wait for a response in milliseconds (if < 0 then wait
   forever)

   Return:
     On success, >= 0
     On error/timeout, < 0
*/
CIVETWEB_API int mg_get_response(struct mg_connection *conn,
                                 char *ebuf,
                                 size_t ebuf_len,
                                 int timeout);

/* Check which features where set when civetweb has been compiled.
   Parameters:
     feature: specifies which feature should be checked
         1  serve files (NO_FILES not set)
         2  support HTTPS (NO_SSL not set)
         4  support CGI (NO_CGI not set)
         8  support IPv6 (USE_IPV6 set)
        16  support WebSocket (USE_WEBSOCKET set)
        32  support Lua scripts and Lua server pages (USE_LUA is set)

   Return:
     If feature is available > 0
     If feature is not available = 0
*/
CIVETWEB_API unsigned mg_check_feature(unsigned feature);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* CIVETWEB_HEADER_INCLUDED */


text:
import isRegExp from 'is-regexp';

export default function stripCssComments(cssString, {preserve = true, whitespace = true, all} = {}) {
	if (all) {
		throw new Error('The `all` option is no longer supported. Use the `preserve` option instead.');
	}

	let preserveImportant = preserve;
	let preserveFilter;
	if (typeof preserve === 'function') {
		preserveImportant = false;
		preserveFilter = preserve;
	} else if (isRegExp(preserve)) {
		preserveImportant = false;
		preserveFilter = comment => preserve.test(comment);
	}

	let isInsideString = false;
	let currentCharacter = '';
	let comment = '';
	let returnValue = '';

	for (let index = 0; index < cssString.length; index++) {
		currentCharacter = cssString[index];

		if (cssString[index - 1] !== '\\' && (currentCharacter === '"' || currentCharacter === '\'')) {
			if (isInsideString === currentCharacter) {
				isInsideString = false;
			} else if (!isInsideString) {
				isInsideString = currentCharacter;
			}
		}

		// Find beginning of `/*` type comment
		if (!isInsideString && currentCharacter === '/' && cssString[index + 1] === '*') {
			// Ignore important comment when configured to preserve comments using important syntax: /*!
			const isImportantComment = cssString[index + 2] === '!';
			let index2 = index + 2;

			// Iterate over comment
			for (; index2 < cssString.length; index2++) {
				// Find end of comment
				if (cssString[index2] === '*' && cssString[index2 + 1] === '/') {
					if ((preserveImportant && isImportantComment) || (preserveFilter && preserveFilter(comment))) {
						returnValue += `/*${comment}*/`;
					} else if (!whitespace) {
						if (cssString[index2 + 2] === '\n') {
							index2++;
						} else if (cssString[index2 + 2] + cssString[index2 + 3] === '\r\n') {
							index2 += 2;
						}
					}

					comment = '';

					break;
				}

				// Store comment text
				comment += cssString[index2];
			}

			// Resume iteration over CSS string from the end of the comment
			index = index2 + 1;

			continue;
		}

		returnValue += currentCharacter;
	}

	return returnValue;
}


text:
<?php

namespace PDepend\Source\AST;

/**
 * This node class represents a break-statement.
 *
 * <code>
 * ------
 * break;
 * ------
 *
 * ---------
 * break 42;
 * ---------
 *
 * ----------------------
 * break $this->foobar();
 * ----------------------
 * </code>
 *
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
 * @since 0.9.12
 */
class ASTBreakStatement extends \PDepend\Source\AST\ASTStatement
{
    /**
     * Accept method of the visitor design pattern. This method will be called
     * by a visitor during tree traversal.
     *
     * @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
     * @param mixed                                 $data
     *
     * @return mixed
     * @since  0.9.12
     */
    public function accept(\PDepend\Source\ASTVisitor\ASTVisitor $visitor, $data = null)
    {
        return $visitor->visitBreakStatement($this, $data);
    }
}


text:
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class AddNullableToLastReadInParticipantsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        DB::statement('ALTER TABLE `'.DB::getTablePrefix().'participants` CHANGE COLUMN `last_read` `last_read` timestamp NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP;');
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
    }
}


text:
const webpack = require('webpack')
const path = require('path')

const BUILD_DIR = path.resolve(__dirname, 'app/static/js')
const APP_DIR = path.resolve(__dirname, 'app/dashboard')

const config = {
  mode: 'development',
  entry: APP_DIR + '/index.js',
  output: {
    path: BUILD_DIR,
    filename: 'dashboard.js',
    hotUpdateChunkFilename: '.cache/hot-update.js',
    hotUpdateMainFilename: '.cache/hot-update.json'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  resolve: {
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [{
      test: /\.jsx?$/,
      use: ['babel-loader'],
      include: APP_DIR
    }]
  }
}

module.exports = config


text: This folder contains Goldilocks Architecture Documents.


text:
/*!
 * \file texture_flatten.cc
 * \brief Flattens texture storage from multi-dimensional array
 * to 2D (width, height) buffer access
 */

#include <tvm/runtime/registry.h>
#include <tvm/te/operation.h>
#include <tvm/tir/builtin.h>
#include <tvm/tir/expr.h>
#include <tvm/tir/stmt.h>
#include <tvm/tir/transform.h>

#include <unordered_map>

#include "../../arith/ir_visitor_with_analyzer.h"
#include "../../runtime/texture.h"
#include "../../runtime/thread_storage_scope.h"

namespace tvm {
namespace tir {
using runtime::ApplyTexture2DFlattening;
using runtime::DefaultTextureLayoutSeparator;
using runtime::IsTextureStorage;

class TextureLoweringBase : public StmtExprMutator {
 public:
  explicit TextureLoweringBase(const Map<Var, Buffer>& extern_buffer_map,
                               IRVisitorWithAnalyzer* bound_analyzer)
      : bound_analyzer_{bound_analyzer} {
    for (auto kv : extern_buffer_map) {
      extern_buf_.insert(kv.second);
    }
  }

  inline PrimExpr SimplifyOffset(const Array<PrimExpr>& shape, const Array<PrimExpr>& index) const {
    PrimExpr base = make_const(DataType::Int(32), 0);
    ICHECK_EQ(shape.size(), index.size());
    if (index.size() > 0) {
      PrimExpr offset = index[0];
      for (size_t i = 1; i < index.size(); ++i) {
        offset = bound_analyzer_->Simplify(offset * shape[i] + index[i]);
      }
      base = base + offset;
    }
    return base;
  }

 protected:
  std::string GetStorageScope(const Buffer& buffer) {
    auto* ptr = buffer->data->type_annotation.as<PointerTypeNode>();
    ICHECK(ptr) << "Buffer Var's type annotation must be of PointerType";
    return ptr->storage_scope;
  }

  // Set of all external input and output buffers
  std::unordered_set<Buffer, ObjectPtrHash, ObjectPtrEqual> extern_buf_;
  // Bound analzer
  IRVisitorWithAnalyzer* bound_analyzer_;
};

// Lower Nd storage access to 2d texture access using lowering convention
// specified by the buffers storage scope.
class TextureFlattener : public TextureLoweringBase {
 public:
  using StmtExprMutator::VisitStmt_;
  explicit TextureFlattener(const Map<Var, Buffer>& extern_buffer_map,
                            IRVisitorWithAnalyzer* bound_analyzer)
      : TextureLoweringBase(extern_buffer_map, bound_analyzer) {}

  Stmt VisitStmt_(const BufferRealizeNode* op) final {
    if (extern_buf_.count(op->buffer)) {
      return this->VisitStmt(op->body);
    }

    std::string storage_scope = GetStorageScope(op->buffer);
    Var buffer_var(op->buffer->data->name_hint,
                   PointerType(PrimType(op->buffer->dtype), String(storage_scope)));
    let_binding_.insert({op->buffer->data, buffer_var});

    Stmt stmt = StmtExprMutator::VisitStmt_(op);
    op = stmt.as<BufferRealizeNode>();

    // Rewrite any buffer realizations with storage scope to 2d texture allocations
    if (IsTextureStorage(storage_scope)) {
      Stmt body = this->VisitStmt(op->body);
      ICHECK(op->bounds.size() >= 3) << "Only 2d RGBA texture is currently supported";
      int vec_length = static_cast<int>(op->bounds.back()->extent.as<IntImmNode>()->value);
      ICHECK(vec_length == 4 || vec_length == 1)
          << "Inner dimension of texture must be vector of length 1 or 4 (RGBA)";

      struct ShapeFromRange {
        const Array<Range>& bounds;
        PrimExpr operator[](size_t i) const { return bounds[i]->extent; }
      };
      size_t axis = DefaultTextureLayoutSeparator(op->bounds.size(), storage_scope);
      auto texture =
          ApplyTexture2DFlattening<PrimExpr>(ShapeFromRange{op->bounds}, op->bounds.size(), axis);
      Array<PrimExpr> args = {texture.width, texture.height};
      stmt = LetStmt(buffer_var, Call(buffer_var.dtype(), builtin::texture2d_alloca(), args), body);
    }

    return stmt;
  }

  Stmt VisitStmt_(const BufferStoreNode* op) final {
    Stmt stmt = StmtExprMutator::VisitStmt_(op);
    op = stmt.as<BufferStoreNode>();
    std::string storage_scope = GetStorageScope(op->buffer);
    // Lower to two dimensional access
    if (IsTextureStorage(storage_scope)) {
      Array<PrimExpr> args = GetTextureAccessArgs(op, op->buffer);
      args.push_back(op->value);
      stmt = Evaluate(Call(args[0]->dtype, builtin::texture2d_store(), args));
    }

    return stmt;
  }

  PrimExpr VisitExpr_(const BufferLoadNode* op) final {
    PrimExpr expr = StmtExprMutator::VisitExpr_(op);
    op = expr.as<BufferLoadNode>();
    // Lower to two dimensional access
    std::string storage_scope = GetStorageScope(op->buffer);
    if (IsTextureStorage(storage_scope)) {
      Array<PrimExpr> args = GetTextureAccessArgs(op, op->buffer);
      args.push_back(op->indices.back());
      expr = Call(op->buffer->dtype, builtin::texture2d_load(), args);
    }

    return expr;
  }

 protected:
  template <typename T>
  Array<PrimExpr> GetTextureAccessArgs(const T* op, const Buffer& buffer) {
    Array<PrimExpr> args;
    if (let_binding_.count(op->buffer->data)) {
      args.push_back(let_binding_[op->buffer->data]);
    } else {
      args.push_back(buffer->data);
    }
    Array<PrimExpr> row_dims, row_indices, col_dims, col_indices;
    for (size_t i = 0; i < op->buffer->shape.size() - 1; i++) {
      if (i < DefaultTextureLayoutSeparator(op->buffer->shape.size(), GetStorageScope(buffer))) {
        col_dims.push_back(op->buffer->shape[i]);
        col_indices.push_back(op->indices[i]);
      } else {
        row_dims.push_back(op->buffer->shape[i]);
        row_indices.push_back(op->indices[i]);
      }
    }
    PrimExpr row_offset = SimplifyOffset(row_dims, row_indices);
    PrimExpr col_offset = SimplifyOffset(col_dims, col_indices);
    args.push_back(row_offset);
    args.push_back(col_offset);
    return args;
  }

  // Bindings to new texture vars with texture pointer scope
  std::unordered_map<Var, PrimExpr, ObjectPtrHash, ObjectPtrEqual> let_binding_;
};

PrimFunc TextureFlatten(PrimFunc func) {
  auto fptr = func.CopyOnWrite();
  IRVisitorWithAnalyzer bound_analyzer;
  bound_analyzer(fptr->body);
  fptr->body = TextureFlattener(fptr->buffer_map, &bound_analyzer)(std::move(fptr->body));
  return func;
}

namespace transform {

Pass TextureFlatten() {
  auto pass_func = [=](PrimFunc f, IRModule m, PassContext ctx) {
    return TextureFlatten(std::move(f));
  };
  return CreatePrimFuncPass(pass_func, 0, "tir.TextureFlatten", {});
}

TVM_REGISTER_GLOBAL("tir.transform.TextureFlatten").set_body_typed(TextureFlatten);

}  // namespace transform

}  // namespace tir
}  // namespace tvm


text:
//
//  All-The-Weathers-Bridging-Header.h
//  All-The-Weathers
//
//  Created by Peter Foti on 10/20/15.
//  Copyright © 2015 Peter Foti. All rights reserved.
//

#ifndef All_The_Weathers_Bridging_Header_h
#define All_The_Weathers_Bridging_Header_h

#endif /* All_The_Weathers_Bridging_Header_h */

#import "MBProgressHUD.h"