|  | import { Place, Choice, Direction, World } from '../world'
import { ProperNoun, ImproperNoun, MalePronouns, FemalePronouns, TheyPronouns } from '../language'
import { Encounter, Stat, Damage, DamageType, Vigor, Side } from '../combat'
import * as Creatures from '../creatures'
import * as Items from '../items'
import { LogLine, nilLog, LogLines } from '../interface'
import { Creature } from '../creature'
import { DevourAction } from '../combat/actions'
import { SurrenderEffect } from '../combat/effects'
import moment from 'moment'
import { VoreAI } from '../ai'
function makeParty (): Creature[] {
  const fighter = new Creatures.Human(new ProperNoun("Redgar"), MalePronouns, {
    stats: {
      Toughness: 20,
      Power: 20,
      Reflexes: 15,
      Agility: 15,
      Willpower: 15,
      Charm: 10
    }
  })
  fighter.title = "Lv. 6 Fighter"
  fighter.equip(new Items.Sword(), Items.EquipmentSlot.MainHand)
  const rogue = new Creatures.Human(new ProperNoun('Lidda'), FemalePronouns, {
    stats: {
      Toughness: 10,
      Power: 15,
      Reflexes: 20,
      Agility: 20,
      Willpower: 15,
      Charm: 20
    }
  })
  rogue.title = "Lv. 5 Rogue"
  rogue.equip(new Items.Dagger(), Items.EquipmentSlot.MainHand)
  const wizard = new Creatures.Human(new ProperNoun('Mialee'), FemalePronouns, {
    stats: {
      Toughness: 10,
      Power: 10,
      Reflexes: 15,
      Agility: 15,
      Willpower: 20,
      Charm: 25
    }
  })
  wizard.title = "Lv. 6 Wizard"
  wizard.equip(new Items.Wand(), Items.EquipmentSlot.MainHand)
  const cleric = new Creatures.Human(new ProperNoun('Jozan'), MalePronouns, {
    stats: {
      Toughness: 15,
      Power: 15,
      Reflexes: 10,
      Agility: 10,
      Willpower: 20,
      Charm: 15
    }
  })
  cleric.title = "Lv. 5 Cleric"
  cleric.equip(new Items.Mace(), Items.EquipmentSlot.MainHand)
  return [fighter, cleric, rogue, wizard]
}
export const Town = (): Place => {
  const home = new Place(
    new ProperNoun('Your home'),
    "A very home-y place"
  )
  const debug = new Place(
    new ProperNoun("Debug Room"),
    "Where weird stuff happens"
  )
  const westAve = new Place(
    new ImproperNoun('West Avenue'),
    "Streets of Sim City"
  )
  const northAve = new Place(
    new ImproperNoun('North Avenue'),
    "Streets of Sim City"
  )
  const eastAve = new Place(
    new ImproperNoun('East Avenue'),
    "Streets of Sim City"
  )
  const southAve = new Place(
    new ImproperNoun('South Avenue'),
    "Streets of Sim City"
  )
  const alley = new Place(
    new ImproperNoun('alley'),
    "A spooky alley"
  )
  const westRoad = new Place(
    new ImproperNoun('road'),
    "West of town"
  )
  const woods = new Place(
    new ImproperNoun('woods'),
    "Scary woods"
  )
  const bosses = new Place(
    new ProperNoun("BOSS ZONE"),
    "Extra scary"
  )
  const square = new Place(
    new ProperNoun("Central Square"),
    "The center of town"
  )
  woods.choices.push(
    new Choice(
      "Fight a wolf",
      "yolo",
      (world, executor) => {
        world.encounter = new Encounter(
          {
            name: "You punched a wolf",
            intro: (world: World) => new LogLine(`You punched a wolf. The wolf is angry.`)
          },
          [executor, new Creatures.Wolf()]
        )
        return new LogLine(`FIGHT TIME`)
      }
    )
  )
  woods.choices.push(
    new Choice(
      "Fight a dire wolf",
      "yolo",
      (world, executor) => {
        world.encounter = new Encounter(
          {
            name: "You punched a dire wolf",
            intro: (world: World) => new LogLine(`You punched a dire wolf. The wolf is angry.`)
          },
          [executor, new Creatures.DireWolf()]
        )
        return new LogLine(`FIGHT TIME`)
      }
    )
  )
  woods.choices.push(
    new Choice(
      "Fight a werewolf",
      "yolo",
      (world, executor) => {
        world.encounter = new Encounter(
          {
            name: "You punched a werewolf",
            intro: (world: World) => new LogLine(`You punched a werewolf. The werewolf is angry.`)
          },
          [executor, new Creatures.Werewolf()]
        )
        return new LogLine(`FIGHT TIME`)
      }
    )
  )
  woods.choices.push(
    new Choice(
      "Fight a dragon",
      "yolo",
      (world, executor) => {
        world.encounter = new Encounter(
          {
            name: "You punched a dragon",
            intro: (world: World) => new LogLine(`You punched a dragon. The dragon is angry.`)
          },
          [executor, new Creatures.Dragon()]
        )
        return new LogLine(`FIGHT TIME`)
      }
    )
  )
  const bossEncounters = [
    new Encounter(
      { name: "Withers & Kenzie", intro: (world: World) => nilLog },
      makeParty().concat([new Creatures.Withers(), new Creatures.Kenzie()])
    ),
    new Encounter(
      { name: "Goldeneye", intro: (world: World) => nilLog },
      makeParty().concat([new Creatures.Goldeneye()])
    ),
    new Encounter(
      { name: "Large Wah", intro: (world: World) => nilLog },
      makeParty().concat([new Creatures.Shingo()])
    ),
    new Encounter(
      { name: "Cafat", intro: (world: World) => nilLog },
      makeParty().concat([new Creatures.Cafat()])
    )
  ]
  home.choices.push(
    new Choice(
      "Nap",
      "Zzzzzz",
      (world, executor) => {
        return new LogLines(
          `You lie down for a nice nap...`,
          world.advance(moment.duration(1, "hour"))
        )
      }
    )
  )
  home.choices.push(
    new Choice(
      "Heal",
      "Become not dead and/or eaten",
      (world, executor) => {
        Object.keys(Vigor).forEach(vigor => {
          executor.vigors[vigor as Vigor] = executor.maxVigors[vigor as Vigor]
        })
        if (executor.containedIn !== null) {
          executor.containedIn.release(executor)
        }
        executor.statusEffects.forEach(effect => {
          executor.removeEffect(effect)
        })
        executor.destroyed = false
        return new LogLine(`You're healthy again`)
      }
    )
  )
  westAve.choices.push(
    new Choice(
      "Eat someone",
      "Slurp",
      (world, executor) => {
        const snack = new Creatures.Human(new ProperNoun(["Snack", "Treat", "Tasty", "Dinner", "Appetizer"][Math.floor(Math.random() * 5)]), [MalePronouns, FemalePronouns, TheyPronouns][Math.floor(Math.random() * 3)])
        snack.applyEffect(new SurrenderEffect())
        const options = executor.validActions(snack).filter(action => action instanceof DevourAction)
        return options[Math.floor(options.length * Math.random())].execute(executor, snack)
      }
    )
  )
  westAve.choices.push(
    new Choice(
      "Fight someone",
      "Ow",
      (world, executor) => {
        const enemy = new Creatures.Human(new ProperNoun("Nerd"), TheyPronouns)
        enemy.side = Side.Monsters
        enemy.ai = new VoreAI()
        const encounter = new Encounter(
          {
            name: "Fight some nerd",
            intro: world => new LogLine(`You find some nerd to fight.`)
          },
          [world.player, enemy]
        )
        world.encounter = encounter
        return nilLog
      }
    )
  )
  square.choices.push(
    new Choice(
      "Fight Geta",
      "yolo",
      (world, executor) => {
        world.encounter = new Encounter(
          {
            name: "You punched Geta",
            intro: (world: World) => new LogLine(`You punched Geta. Geta is angry.`)
          },
          [executor, new Creatures.Geta()]
        )
        return new LogLine(`FIGHT TIME`)
      }
    )
  )
  square.choices.push(
    new Choice(
      "Buy a shiny rock",
      "This rock has no use.",
      (world, executor) => {
        if (executor.wallet.Gold >= 500) {
          executor.wallet.Gold -= 500
          executor.items.push(
            new Items.KeyItem(new ProperNoun("Shiny Rock"), "Very shiny")
          )
          return new LogLine(`You buy a shiny rock`)
        } else {
          return new LogLine(`Shiny rocks are 500 gold coins, loser!`)
        }
      }
    )
  )
  alley.choices.push(
    new Choice(
      "Kuro",
      "Get eaten by a Luxray",
      (world, executor) => {
        const enemy = new Creatures.Kuro()
        enemy.ai = new VoreAI()
        const encounter = new Encounter(
          {
            name: "Luxray time",
            intro: world => new LogLine(`Luxray time!`)
          },
          [world.player, enemy]
        )
        world.encounter = encounter
        return nilLog
      }
    )
  )
  bossEncounters.forEach(encounter => {
    bosses.choices.push(
      new Choice(
        encounter.desc.name,
        "Boss fight!",
        (world, executor) => {
          world.encounter = encounter
          return nilLog
        }
      )
    )
  })
  debug.choices.push(
    new Choice(
      "Cut stats",
      "Make your stats less good-er",
      (world, executor) => {
        Object.keys(Stat).forEach(stat => {
          executor.baseStats[stat as Stat] -= 5
          executor.takeDamage(new Damage(
            { amount: 5, target: (stat as Stat), type: DamageType.Pure }
          ))
        })
        return new LogLine(`You're weaker now`)
      }
    )
  )
  debug.choices.push(
    new Choice(
      "Boost stats",
      "Make your stats more good-er",
      (world, executor) => {
        Object.keys(Stat).forEach(stat => {
          executor.baseStats[stat as Stat] += 5
          executor.takeDamage(new Damage(
            { amount: 5, target: (stat as Stat), type: DamageType.Heal }
          ))
        })
        return new LogLine(`You're stronger now`)
      }
    )
  )
  debug.choices.push(
    new Choice(
      "Grow",
      "Make yourself larger",
      (world, executor) => {
        executor.voreStats.Mass *= 1.5
        return new LogLine(`You're larger now`)
      }
    )
  )
  debug.choices.push(
    new Choice(
      "Shrink",
      "Make yourself smaller",
      (world, executor) => {
        executor.voreStats.Mass /= 1.5
        return new LogLine(`You're smaller now`)
      }
    )
  )
  debug.choices.push(
    new Choice(
      "Set Name",
      "Set your name",
      (world, executor) => {
        const input = prompt("Enter a name")
        if (input !== null) {
          executor.baseName = new ProperNoun(input)
          return new LogLine(`Your new name is ${executor.baseName}.`)
        } else {
          return new LogLine(`nvm`)
        }
      }
    )
  )
  debug.choices.push(
    new Choice(
      "Add money",
      "Get some money",
      (world, executor) => {
        executor.wallet.Gold += 1000
        return new LogLine(`$$$$$$$$$$$$$$$$$`)
      }
    )
  )
  home.biconnect(Direction.South, debug)
  debug.biconnect(Direction.South, bosses)
  home.biconnect(Direction.North, westAve)
  westAve.biconnect(Direction.West, westRoad)
  westAve.biconnect(Direction.North, alley)
  westRoad.biconnect(Direction.South, woods)
  square.biconnect(Direction.East, eastAve)
  square.biconnect(Direction.West, westAve)
  square.biconnect(Direction.North, northAve)
  square.biconnect(Direction.South, southAve)
  return home
}
 |