//

//  File.swift

//  

//

//  copywrite by Coty Ryan Miller on 10/5/17.

//

// v0.1.2b

//

import Foundation


var playGame = true // set to false on exit.


var HealthPoints = 40     // Start with 40HP

let maxHealthPoints = 80  // Max HP is 80.


var causeOfDeath = 0


//

// CurrentRoomNumber will let us check what room we are in to find what

// options we have in the room as well as the dungeon text to display.

//

var currentRoomNumber = 1


let actions: [String:Int] = ["look":1,

                             "go":2,   // Best part of using dictionaries is the actions

                             "walk":2, // "go" and "walk" can easaly be treated as the same.

                             "use":3,

                             "throw":4,

                             "drop":4,

                             "take":5,    // See?

                             "pick up":5, // We did it again! ;-)

                             "consume":6,

                             "eat":6,

                             "check pockets":7,

                             "talk":8,

                             "talk to":9

                            ]


let directions: [String:Int] = ["north":1,

                                "east":2,

                                "south":3,

                                "west": 4,

                                "up": 5,

                                "down": 6]


//---------------------------------------------------------------------

// An array for all known items names to check the "itemLocation"

// Dictionary.

//

let allItems: [String] = ["sand",

                          "cypher",

                          "sword",

                          "BroachOfHigz"]

//

// Item location, ie: if "Cypher":6, then the cypher is in room 6.

// But if cypher is 0, then it's in the invintory.

//

// 0xFFFFFF01 - 0xFFFFFFFF is reserved for characters to give items.

//

var itemLocation: [String:Int] = ["cypher":6,

                                  "sword":0xFFFFFF01,

                                  "BroachOfHigz":0xFFFFFF01

]

//---------------------------------------------------------------------


let stringAteSand  = "You ate the sand, your mouth is now very dry."

let StringLookUp0  = "You Look up and see "

    let whatsUp0   = "Darkness"

    let whatsUp1   = "A beutiful sky with some birds."


let stringLookDown0 = "You look down to see your feet "

let stringLookDown1 = stringLookDown0 + " and a mysterious object"


    let ColoredBlock = "█"

    let ShadedBlock = "░"


//var items: [String:Int] = ["sand":1] // You start out with just sand in your pocket...




// Imma use room six as an example for how items work here.

// If we pick up the cypher from room six then we remove data

// from the string "roomSixItems" so that the name no longer anounces

// that there is an item there. We will then set have "haveCypher" to

// "true" so that it apears in the invintory.

//


let DungeonText: [Int:String] = [

    0:"Man you evil.",

    

    1:"You stand in a feild surrounded by trees. To the west is a bridge leading over the river. To the north stands a shanty shack and to your east stands a crazed looking man.",

    

    2:"You stand on a bridge. To the east is a small island, to your west lies the mainland.",

    

    3:"A man to your north sits quietly under a tree. To your west lies is a suspicious looking tunel, to your east stands a rickety bridge.",

    

    4:"A man shouting 'THE LOSER DEFEATED THE WUB WUB' in dancing to the west, to your north lies a an earie tunnel, to your east lies a bridge.",

    

    5:"You stand in a dark tunnel, a bright light shines from your south and a dim light to your north.",

    

    6:"You are in a dark room, to the south you see a tunnel with a bright light. You see light shining through some cracks that make out a faint image of a door to the east. ",

    7:"Whoah, budy! Can't let you do that yet!",

    

    8:"You stand within a rickity shack. Sitting on a rug sits a raisin of a man who apears to be in deap meditation. To your south lies a rickety door."

    

    ]


//

// These lines allow us to keep track of what rooms are North/East/South/west

// of "currentRoomNumber" So we know what text/items to load when user types

// something like "go north"

//

let whatsNorthOf: [Int:Int] = [1:8, 4:5, 5:6]


let whatsEastOf:  [Int:Int] = [4:3, 3:2, 2:1,

                                 6:7]


let whatsSouthOf: [Int:Int] = [6:5, 5:4, 8:1]


let whatsWestOf:  [Int:Int] = [1:2, 2:3, 3:4,

                               7:6]

//

// These 4 vars dictate what (If anything) blocks the players path, and

// defines the item required to pass.

//

// For example, in the begining the player is stopped from crossing the bridge

// to the west from the island to the main land by a gaurd, this is handled by:

//

//   > var WestIsBlockedOf: [Int:String] = [2:"BroachOfHigz"]

//

// See also: var PathBlockedText

//

var NorthIsBlockedOf: [Int:String] = [0xFF:""]

var EastIsBlockedOf: [Int:String] = [0xFF:""]

var SouthIsBlockedOf: [Int:String] = [0xFF:""]

var WestIsBlockedOf: [Int:String] = [2:"BroachOfHigz"]

//

// If the path is blocked "var PathBlockedText" holds the text descibing that 

// the path is blocked.

//

let PathBlockedText: [Int:String] = [2:"A gaurd blocks your path to the west..."]


let CharactersToGive: [Int:String] = [8:"BroachOfHigz" // Character in room 8 gives "BroachOfHigz"

    ] // Also see "let CharactersToGiveIf"


/************************************************************************

 * Charachter chats

 ***********************************************************************/


let OriginChar: [Int:String] = [1:"efwihu efgrsu ewio haefguw enyrtu ekunrwagiqul!?",

                                2:"I have been instruction to not let anyone pass onto the main land without the BroachOfHigz. It is the law; and the law is my job!",

                                8:"In order to cross the bridge onto the main land, you'll need this."

]


let CharecterDesciption: [Int:String] = [

        1:"A crazed looking man speaking jibberish stand to your east.",

        8:"sitting on a rug sits a raisin of a man who apears to be in deap meditation. To your south lies a rickety door."

    ]

//

// Char Item Flag dictates that if an item is present in the players

// inventory, then instead of displaying the 'OriginChar' message we will

// Display the 'OptionChar' message instead.

//

// In the case of the "crazed man" in the begining, if the player is equiped

// with a cypher he will be abvle to understand him.

//

let CharItemFlag: [Int:String] = [1:"cypher", 8:"BroachOfHigz"]


let OptionChar: [Int:String] = [1:"Aha! I see you have found my cypher! Exelent! People think I'm crazy, but really I just speak a different language! Ahaha! Ah yes, anyway, since you have found my cypher take this as a gift!",

                                8:"I wish you safe travels my son."]


//

//

//

let CharactersToGiveIf: [Int:String] = [1:"sword"]

/************************************************************************

 * Battle Screen Handler

 ***********************************************************************/

var battleMap: [Int:Bool] = [4:true] // If room number is true, then an

                                     // Un-fought battle resides in that 

                                     // room and 

                                     // doBattle(RoomNum: currentRoomNumber)

                                     // should be launched.

func doBattle(roomNum: Int)

{

    //--------------------------------------------------------------------

    // An example battle in room 4.

    //--------------------------------------------------------------------

    if(roomNum == 4)

    {

        print("A crazed wub wub apeared!")

        print("")

        print("Throw sand? ")

        print("[yes/no]:", terminator: "")

        let wubwub = readLine()!

        

        if wubwub == "yes"

        {

            print("You threw sand at the wub wub")

            print("")

            print("The wub wub ran away.")

            battleMap[4] = false

        }

        else

        {

            HealthPoints = HealthPoints - 40

            print("The crazed WubWub WubWubed you and ran off.")

            print(" ")

            print("The wub wub dealt 40 damage.")

            causeOfDeath = 4

        }

    }

}

/************************************************************************

 * Slow print function, slowly prints a string to emulate the old like

 * "DOS" experience thats like retro or whatever.

 ***********************************************************************/

func SPrint(words: String)

{

    let newWords = Array(words.characters)

    let nSize = newWords.count

    for i in 1...nSize - 1

    {

        print(newWords[i], terminator: "")

        

        usleep(50 * 1000) // sleep for 50 Milliseconds.

    }

    print("")

}

/************************************************************************

 * Draw the fancy @$$ dope status bar YOOO!

 ***********************************************************************/

    func drawCountDown(outOf: Int)

    {

        if outOf < 80 {

            for _ in 1...outOf

            {

                print(ColoredBlock, terminator:"")

            }

            let outIn = 80 - outOf

            for _ in 1...outIn

            {

                print(ShadedBlock, terminator:"")

            }

        }

        // If the request is to draw 80 or more blocks...

        // just draw a solid black bar.

        else

        {

            for _ in 1...80

            {

                print(ColoredBlock, terminator:"")

            }

        }

    }

/************************************************************************

 * Print a string with blocks at both sides

 ***********************************************************************/

func printWithBlocks(text: String) {

    print(ColoredBlock, terminator:"")


    print(text, terminator: "")

    

        // some maths

    var maths = text.characters.count

    maths = 78 - maths

    

    for _ in 1...maths

    {

        print(" ", terminator: "")

    }

    

    print(ColoredBlock)

    

}

/************************************************************************

 * Clear lines/screen function or whatever

 ***********************************************************************/

    func clear(times: Int) {

        for _ in 1...times {

            print(" ")

        }

    }

/************************************************************************

 * Clear lines/screen function with blocks on both sides

 ***********************************************************************/

func clearWithBlocks(times: Int) {

    for _ in 1...times {

        print(ColoredBlock, terminator:"")

        for _ in 1...78

        {

            print(" ", terminator:"")

        }

        print(ColoredBlock)

    }

}

/************************************************************************

 * print the cypher key... It's a seperate function because, fuck you.

 ***********************************************************************/

func printCypherKey()

{

    print("                  Z   A  B")

    print("               Y            C")

    print("            X                 D")

    print("           W                    E")

    print("          V                      F")

    print("         U                        G")

    print("         T            @           H")

    print("          S                       I")

    print("           R                     J")

    print("             Q                 K")

    print("               P            L ")

    print("                 O   N   M")

}

/************************************************************************

 * main loop yo.

 ***********************************************************************/

clear(times: 24)


print("Your HP is \(HealthPoints)/\(maxHealthPoints)")

print(" ")

while playGame == true

{

    //

    // If current room has an undefeated monster... KILL IT

    //

    if(battleMap[currentRoomNumber]==true){doBattle(roomNum: currentRoomNumber)}

    //

    // Print Dungeon area desciption...

    //

    print(

        DungeonText[currentRoomNumber] ??               // diplay room text.

        "room# \(currentRoomNumber) in Library is NIL"  // Displays if room doesn't exsist.

    )

    print(" ")

    //--------------------------------------------------------------

    // Print Items in the room.

    //--------------------------------------------------------------

    var temp0 = allItems.count - 1

    repeat {

        if(itemLocation[allItems[temp0]] == currentRoomNumber)

        {

            print("At your feet you see a shadowy silhouette.")

            print(" ")

        }

        temp0 = temp0 - 1

    } while(temp0 != 0)

    //---------------------------------------------------------------

    // Print if their is a blocked path in some direction...

    //---------------------------------------------------------------

    let Pathib = PathBlockedText[currentRoomNumber] ?? ""

    if Pathib != ""

    {

        let aa = NorthIsBlockedOf[currentRoomNumber] ?? ""

        let ab = EastIsBlockedOf[currentRoomNumber]  ?? ""

        let ac = SouthIsBlockedOf[currentRoomNumber] ?? ""

        let ad = WestIsBlockedOf[currentRoomNumber]  ?? ""

        

        let ba = itemLocation[aa] ?? 0

        let bb = itemLocation[ab] ?? 0

        let bc = itemLocation[ac] ?? 0

        let bd = itemLocation[ad] ?? 0

        

        if(ba != 0 || bb != 0 || bc != 0 || bd != 0)

        {

            print("")

            print(Pathib)

            print("")

        }

    }

    //---------------------------------------------------------------

    // Print Player HealthPoints

    //---------------------------------------------------------------

    print(" ")

    print(": ", terminator:"")

    

    var inputBuffer0 = readLine()!

    

    //-----------------------------------------------------------------

    // Handle "look"

    //-----------------------------------------------------------------

    if(actions[inputBuffer0] == 1)

    {

        print("Look at what?")

        print(" ")

        print(": ", terminator:"")

        

        var inputBuffer1 = readLine()!


        if(inputBuffer1 == allItems[0])

        {

            print("You take the sand out of your pocket and run it's course grain through your fingers")

            print(" ")

        }

        if(inputBuffer1 == allItems[1])

        {

            if(itemLocation["cypher"] == 0){printCypherKey()}

        }

    }

    //-----------------------------------------------------------------

    // Handle "go"

    //-----------------------------------------------------------------

    if(actions[inputBuffer0] == 2)

    {

        print("Go where?")

        print(" ")

        print(": ", terminator:"")

        var inputBuffer1 = readLine()!

        

        let roomBackUp = currentRoomNumber // save the room number incase

                                           // we get an invalid request.

        

        //-------------------------------------------------------------

        // Handle go north

        //-------------------------------------------------------------

        if(directions[inputBuffer1] == 1)

        {

            let NiBo = NorthIsBlockedOf[currentRoomNumber] ?? ""

            if NiBo == "" // if NiBo == "", then path is not blocked

            {

                // load desired room number for North into the current room number

                // Register.

                 currentRoomNumber = whatsNorthOf[currentRoomNumber] ?? 0

            }

            else

            {

                let PiBT = PathBlockedText[currentRoomNumber] ?? ""

                if PiBT == ""  // Verrify PiBT is not empty... and warn dev tester

                               // if it is.

                {

                    print("!: Path block text must be set!")

                }

                else

                {

                    // Check to see if the player has required item to pass in

                    // their inventory.

                    if itemLocation[NiBo] == 0

                    {

                        currentRoomNumber = whatsNorthOf[currentRoomNumber] ?? 0

                    }

                    else

                    {

                        // If not... Rub it in their face!

                        print("")

                        print(PiBT)

                        print("")

                    }

                }

            }

        }

        //-------------------------------------------------------------

        // Handle go East

        //-------------------------------------------------------------

        if(directions[inputBuffer1] == 2)

        {

            let EiBo = EastIsBlockedOf[currentRoomNumber] ?? ""

            if EiBo == "" // if EiBo == "", then path is not blocked

            {

                // load desired room number for East into the current room number

                // Register.

                currentRoomNumber = whatsEastOf[currentRoomNumber] ?? 0

            }

            else

            {

                let PiBT = PathBlockedText[currentRoomNumber] ?? ""

                if PiBT == ""

                {

                    print("!: Path block text must be set!")

                }

                else

                {

                    // Check to see if the player has required item to pass in

                    // their inventory.

                    if itemLocation[EiBo] == 0

                    {

                        currentRoomNumber = whatsEastOf[currentRoomNumber] ?? 0

                    }

                    else

                    {

                        // If not... Rub it in their face!

                        print("")

                        print(PiBT)

                        print("")

                    }

                }

            }

        }

        //-------------------------------------------------------------

        // Handle go South

        //-------------------------------------------------------------

        if(directions[inputBuffer1] == 3)

        {

            let SiBo = SouthIsBlockedOf[currentRoomNumber] ?? ""

            if SiBo == "" // Is path blocked?

            {

                // load desired room number for South into the current room number

                // Register.

                currentRoomNumber = whatsSouthOf[currentRoomNumber] ?? 0

            }

            else

            {

                let PiBT = PathBlockedText[currentRoomNumber] ?? ""

                if PiBT == ""

                {

                    print("!: Path block text must be set!")

                }

                else

                {

                    // Check to see if the player has required item to pass in

                    // their inventory.

                    if itemLocation[SiBo] == 0

                    {

                        currentRoomNumber = whatsSouthOf[currentRoomNumber] ?? 0

                    }

                    else

                    {

                        // If not... Rub it in their face!

                        print("")

                        print(PiBT)

                        print("")

                    }

                }

            }

        }

        //-------------------------------------------------------------

        // Handle go West.

        //-------------------------------------------------------------

        if(directions[inputBuffer1] == 4)

        {

            let WiBo = WestIsBlockedOf[currentRoomNumber] ?? ""

            if WiBo == "" // Is path blocked?

            {

                // load desired room number for West into the current room number

                // Register.

                currentRoomNumber = whatsWestOf[currentRoomNumber] ?? 0

            }

            else

            {

                let PiBT = PathBlockedText[currentRoomNumber] ?? ""

                if PiBT == ""

                {

                    print("!: Path block text must be set!")

                }

                else

                {

                    // Check to see if the player has required item to pass in

                    // their inventory.

                    if itemLocation[WiBo] == 0

                    {

                        currentRoomNumber = whatsWestOf[currentRoomNumber] ?? 0

                    }

                    else

                    {

                        // If not... Rub it in their face!

                        print("")

                        print(PiBT)

                        print("")

                    }

                }

            }

        }

        //-------------------------------------------------------------

        // Temporary handlers for go up/down...

        //-------------------------------------------------------------

        if(directions[inputBuffer1] == 5){print("You jumped, but nothing happened...")}

        if(directions[inputBuffer1] == 6){print("You layed down, but nothing happened...")}

        

        //-------------------------------------------------------------

        // If the "currentRoomNumber" is 0 then we have an invalid

        // request. So let the player know and restore 

        // "currentRoomNumber" from "roomBackUp"

        //-------------------------------------------------------------

        if currentRoomNumber == 0

        {

            print("You cannot transverse that direction")

            currentRoomNumber = roomBackUp

        }

        

        causeOfDeath = 0

    }

    if(actions[inputBuffer0] == 3)

    {

        print("Cannot go Use Things yet...")

    }

    //-----------------------------------------------------------

    // Throw Item Handler

    //-----------------------------------------------------------

    if(actions[inputBuffer0] == 4)

    {

        print("Throw what?")

        print(" ")

        print(": ", terminator:"")

        var inputBuffer1 = readLine()!

        

        if inputBuffer1 == "sand" {print("You threw sand and watched it scatter.")}

        print(" ")

        

        var temp0 = allItems.count - 1

        repeat {

            if(itemLocation[allItems[temp0]] == 0)

            {

                if inputBuffer1 == allItems[temp0]

                {

                    print(" ")

                    print("You tossed " + inputBuffer1)

                    print(" ")

                    //

                    // Place the item on the floor of current room.

                    //

                    itemLocation[allItems[temp0]] = currentRoomNumber

                }

            }

            temp0 = temp0 - 1

        } while(temp0 != 0)

        

    }

    //-----------------------------------------------------------

    // Pick up item handler.

    //-----------------------------------------------------------

    if(actions[inputBuffer0] == 5)

    {

        // check if there is an item in the room

        var temp1 = allItems.count - 1

        var itemInRoom = "          "

        

        repeat {

            if(itemLocation[allItems[temp1]] == currentRoomNumber)

            {

                print("You pick up a, "

                    + allItems[temp1]

                    + " and place it in your pocket."

                )

                print(" ")

                

                itemLocation[allItems[temp1]] = 0

            }

            temp1 = temp1 - 1

        } while(temp1 != 0)

    }

    //-----------------------------------------------------------

    // Food Handler

    //-----------------------------------------------------------

    if(actions[inputBuffer0] == 6)

    {

        print("Eat what?")

        print(" ")

        print(": ", terminator:"")

        var inputBuffer1 = readLine()!

        

        if(inputBuffer1 == "sand")

        {

            print(stringAteSand)

            print(" ")

            print("You lost 10 HP")

            HealthPoints = HealthPoints - 10

            

            causeOfDeath = 1

        }

    }

    //-----------------------------------------------------------

    // check pockets action (TODO: make less sloppy)

    //-----------------------------------------------------------

    if(actions[inputBuffer0] == 7)

    {

        print("You check your pockets to find:")

        print("Sand(∞)")

        print("Peanuts(3)")

        if(itemLocation["cypher"] == 0){print("Cypher Key")}

        if(itemLocation["sword"] == 0){print("Basic Sword")}

        print(" ")

    }

    //-----------------------------------------------------------

    // Talk command

    //-----------------------------------------------------------

    // CharactersToGive

    if(actions[inputBuffer0] == 8 || actions[inputBuffer0] == 9)

    {

        if(actions[inputBuffer0] == 8 )

        {

            // Get required Item for character change of status.

            let _CIF = CharItemFlag[currentRoomNumber] ?? ""

            // Get location of afformentioned item

            let _iL  = itemLocation[_CIF] ?? 0xFF

            

            // If _iL is 0 then the item is in the players inventory.

            if(_iL == 0)

            {

                print(OptionChar[currentRoomNumber] ?? "wut")

                

                // Check if there is an item to give the charecter during

                // the optional Charecter State.

                // CharactersToGiveIf

                

                let itemB = CharactersToGiveIf[currentRoomNumber] ?? ""

                if itemB != ""

                {

                    let checkInv = itemLocation[itemB]

                    if checkInv != 0

                    {

                        print("")

                        print("You recieved ", itemB)

                        print("")

                        itemLocation[itemB] = 0

                    }

                }


            } else {

                print(

                    OriginChar[currentRoomNumber] ??               // diplay room text.

                    // Displays if room doesn't exsist.

                    "You talk outload... There is no one around to here you."

                )

            }

            let itemB = CharactersToGive[currentRoomNumber] ?? ""

            if itemB != ""

            {

                let checkInv = itemLocation[itemB]

                if checkInv != 0

                {

                    print("")

                    print("You recieved ", itemB)

                    print("")

                    itemLocation[itemB] = 0

                }

            }


        }

        else

        {

            print("Talk to whom?")

        }

    }

    //-----------------------------------------------------------

    // Handle player death

    //-----------------------------------------------------------

    if HealthPoints <= 0

    {

        print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~You have died~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

        print(" ")

        print("Cause of death:")

        print(" ")

        if(causeOfDeath==0){print(" - Unknown.")}

        if(causeOfDeath==1){print(" - Sheer stupidity.")}

        if(causeOfDeath==2){print(" - Killed by troll.")}

        if(causeOfDeath==3){print(" - Burned Alive.")}

        if(causeOfDeath==4){print(" - Killed by a WubWub.")}

        print(" ")

        playGame = false

    }

    //drawCountDown(outOf: 80)

    //printWithBlocks(text: " Hello World")

    //clearWithBlocks(times: 21)

    //drawCountDown(outOf: 40)

    //playGame = false

}