func LevelToExperience(lvl int) int {
	if lvl < 2 {
		return 0
	}
	if lvl > len(experienceLevels)-2 {
		return int(experienceLevels[len(experienceLevels)-1])
	}
	return int(experienceLevels[lvl-2])
}
LevelToExperience Finds the experience required for the specified level
package entity
import (
	"math"
	"strconv"
	"sync"
	"github.com/lithammer/fuzzysearch/fuzzy"
)
const (
	StatAttack int = iota
	StatDefense
	StatStrength
	StatHits
	StatRanged
	StatPrayer
	StatMagic
	StatCooking
	StatWoodcutting
	StatFletching
	StatFishing
	StatFiremaking
	StatCrafting
	StatSmithing
	StatMining
	StatHerblaw
	StatAgility
	StatThieving
)
var mask = ^3
type SkillTable struct {
	current    [18]int
	maximum    [18]int
	experience [18]int
	sync.RWMutex
}
func (s *SkillTable) Current(idx int) int {
	s.RLock()
	defer s.RUnlock()
	return s.current[idx]
}
func (s *SkillTable) DeltaMax(idx int) int {
	return s.Maximum(idx) - s.Current(idx)
}
func (s *SkillTable) DecreaseCur(idx, delta int) {
	s.Lock()
	defer s.Unlock()
	s.current[idx] -= delta
}
func (s *SkillTable) IncreaseCur(idx, delta int) {
	s.Lock()
	defer s.Unlock()
	s.current[idx] += delta
}
func (s *SkillTable) SetCur(idx, val int) {
	s.Lock()
	defer s.Unlock()
	s.current[idx] = val
}
func (s *SkillTable) DecreaseMax(idx, delta int) {
	s.Lock()
	defer s.Unlock()
	s.maximum[idx] -= delta
}
func (s *SkillTable) IncreaseMax(idx, delta int) {
	s.Lock()
	defer s.Unlock()
	s.maximum[idx] += delta
}
func (s *SkillTable) SetMax(idx, val int) {
	s.Lock()
	defer s.Unlock()
	s.maximum[idx] = val
}
func (s *SkillTable) SetExp(idx, val int) {
	s.Lock()
	defer s.Unlock()
	s.experience[idx] = val
}
func (s *SkillTable) IncExp(idx, val int) {
	s.Lock()
	defer s.Unlock()
	s.experience[idx] += val
}
func (s *SkillTable) Maximum(idx int) int {
	s.RLock()
	defer s.RUnlock()
	return s.maximum[idx]
}
func (s *SkillTable) Experience(idx int) int {
	s.RLock()
	defer s.RUnlock()
	return s.experience[idx]
}
func (s *SkillTable) String() (s1 string) {
	s1 += "{"
	for i := 0; i < 17; i++ {
		s1 += strconv.Itoa(s.Current(i))
		s1 += "/" + strconv.Itoa(s.Maximum(i))
		s1 += " (" + strconv.Itoa(s.Experience(i)) + "),"
	}
	return s1 + "}"
}
func (s *SkillTable) CombatLevel() int {
	s.RLock()
	defer s.RUnlock()
	strengthAvg := float64(s.maximum[StatAttack]+s.maximum[StatStrength]) * .25
	defenseAvg := float64(s.maximum[StatDefense]+s.maximum[StatHits]) * .25
	magicAvg := float64(s.maximum[StatPrayer]+s.maximum[StatMagic]) * .125
	rangedAvg := float64(s.maximum[StatRanged]) * .375
	return int(math.Floor(defenseAvg + magicAvg + math.Max(strengthAvg, rangedAvg)))
}
var skillNames = []string{"attack", "defense", "strength", "hits", "ranged", "prayer", "magic", "cooking",
	"woodcutting", "fletching", "fishing", "firemaking", "crafting", "smithing", "mining", "herblaw", "agility",
	"thieving"}
func SkillName(id int) string {
	for idx, name := range skillNames {
		if idx == id {
			return name
		}
	}
	return "nil"
}
func SkillIndex(s string) int {
	matches := fuzzy.RankFindNormalizedFold(s, skillNames)
	if len(matches) == 0 {
		return -1
	}
	return matches[0].OriginalIndex
}
var experienceLevels [105]uint64
func init() {
	accumulativeExp := uint64(0)
	for lvl := 0; lvl < len(experienceLevels); lvl++ {
		curLvl := float64(lvl + 1)
		exp := curLvl + 300*math.Pow(2, curLvl/7)
		accumulativeExp += uint64(exp)
		experienceLevels[lvl] = accumulativeExp & uint64(mask)
	}
}