python early:


#########################################################################################
#                                                                                       #
#     ██╗  ██╗ ██████╗ ██╗    ██╗    ████████╗ ██████╗     ██╗   ██╗███████╗███████╗    #
#     ██║  ██║██╔═══██╗██║    ██║    ╚══██╔══╝██╔═══██╗    ██║   ██║██╔════╝██╔════╝    #
#     ███████║██║   ██║██║ █╗ ██║       ██║   ██║   ██║    ██║   ██║███████╗█████╗      #
#     ██╔══██║██║   ██║██║███╗██║       ██║   ██║   ██║    ██║   ██║╚════██║██╔══╝      #
#     ██║  ██║╚██████╔╝╚███╔███╔╝       ██║   ╚██████╔╝    ╚██████╔╝███████║███████╗    #
#     ╚═╝  ╚═╝ ╚═════╝  ╚══╝╚══╝        ╚═╝    ╚═════╝      ╚═════╝ ╚══════╝╚══════╝    #
#                                                                                       #
#########################################################################################

    """

    This is a big boy here. First thing to know, we have two cds :
        "quest" and "quest_with_part".
            The first one is for a quest with no sub quests in it.
            The second is here if you have.

    We'll first see how to use "quest", since "quest_with_part" is the same with a thing to add.

    So basically, you start like all the cds by calling it, and here we'll not have anything to add before ":"

        quest:

    Now that we have call our cds, we will add some arguments. For now, we have 8 different you can give:

        - name        : The name of your quest. Have to be between ""
                            ex : name "The hostess with Moistess"

        - description : A desciption for you quest. Here you can have a block or not.
                        If not, your description will be the only one possible and it'll always show.
                            ex : description "Cassandra need to be punished. more... MORE !"

                        If you start a block, then that's because you want your description to change sometimes.
                        In this block, you'll add all the description you want, then "if" and then a condition for when you want it.
                        Be aware that to choose the description, the game will start at the first one until he find one with a True condition.

                            ex:   description:
                                      "First description" if False
                                      "Second description" if True == True and False == False
                                      "Third description" if True

                                Here the third description will never shows up, since the second one is always True.

        - pic         : The name of the pic to be displayed. Between ""
                        ex :   pic "quest.png"

        - keyword     : A string to find the quest more easily.

        - category    : In wich category your quest will appear. Main Staff or Students
                            ex : category "Main"

        - show_cond   : The condition for you quest to be displayed or not.
                            ex : show_cond quest_can_show == True

        - stop_show   : Same for when you want your quest not to be displayed (not necessary since you can add your condition inversed in can_show)
                            ex : stop_show quest_no

        - step        : calling this argument will add a step to your quest. You can add a number or a string or a python expression which will be displayed before the step:
                            ex : step "a"                 ->    a)
                                 step 1                   ->    1)
                                 step 1 if False else 8   ->    8)

                        in this step, you'll add some arguments. Don't forget the ":" at the end of the step line.
                        The argument you can have are :

                            - text : Same as description argument, you can either have it on one line, then only this text will be displayed for this step.
                                     Or you can have it has a block, and then you'll write multiple text with a "if" and a condition to tell when you want the text to appear.

                                         ex:  text:
                                                 "My first text" if cass1
                                                 "My second text" if cass2
                                                 "My third text"                       <-- If no condition is given, then it'll be True.

                                          Don't forget that it'll take the first text with a True condition associated.

                            - show if : When do you want this step to be shown.
                                            ex: show if cass_sex

                            - complete if : When do you want this step to be complete. If this argument is not set, the step will be completed when the next step will be shown.
                                                ex : complete if cass_anal


        - part_cond   : Only useful if you've used the "quest_with_parts" cds, the game will only show the part you're in when this condition is True.


    And that's it for "quest" !


    Now "quest_with_part". After calling it (Without forgetting the ":" at the end), you'll tell him the name of your part.
        ex :     quest_with_part:
                     "My First Part":

    And then it'll work exactly like "quest" cds.

    Note : Only the [name, description, show_cond, stop_cond, category,pic] of the first part will be used. You don't have to write them for the other parts.
    Note 2 : If only one part can be shown, it'll work like a normal quest. When clicking on the quest name, you'll see this part. See Rachel's quest.

    Here an example :

        quest_with_part:

            "Part one":

                name "My quest name"
                pic "quest.pic"
                description "My quest description"
                category "Students"

                step 1:
                    text:
                        "The first step of the first part" if condition
                        "Finally I don't want that" if True
                    show if quest_started
                    complete if quest_first_part_finished

            "part two":

                part_cond part_two_start

                step 1:
                    text "This is the first step of the second part of the quest"
                    show if quest_started


    Yes, I know it's a little weird to have the part name written before the quest name, but it was the easier solution for me not to rewrite the entire class, so... Sorry :D
    """

    def quest_with_part_parse(lexer):
        parts = []

        subblock = lexer.subblock_lexer()

        while subblock.advance():
            name = subblock.string()
            part_arg = {"quest_part_name":name}
            part_arg2 = quest_parse(subblock,True)
            for i in part_arg2:
                part_arg[i] = part_arg2[i]
            parts.append(part_arg)

        return parts

    def quest_parse(lexer,parts=False):

        args = {
                 "quest_var_name" : "",
                 "name" : "",
                 "description" : [],
                 "pic" : "",
                 "category" : "",
                 "steps" : [],
                 "show_cond" : "True",
                 "stop_show" : "False",
                 "part_cond" : "True",
                 "keyword"   : ""
                }

        args["quest_var_name"] = lexer.string()

        subblock = lexer.subblock_lexer()

        while subblock.advance():

            arg = subblock.word()

            if arg != "step":
                if arg == "description":
                    if subblock.has_block():
                        sd = subblock.subblock_lexer()
                        while sd.advance():
                            args["description"].append(quest_step_text_parse(sd))
                    else:
                        args["description"].append(quest_step_text_parse(subblock))
                elif arg != "show_cond" and arg != "stop_show" and arg != "part_cond":
                    args[arg] = subblock.string()
                else:
                    args[arg] = subblock.rest()
            else:
                args["steps"].append(quest_new_step_parse(subblock.delimited_python(":"),subblock.subblock_lexer()))

        if parts:
            return args
        args["quest_part_name"] = ""
        return [args]

    def quest_new_step_parse(number,subblock):

        step = {"number" : number,
                "name" : "",
                "show if" : "True",
                "complete if" : "Next",
                "text":[]
                }

        while subblock.advance():

            arg = subblock.word()

            if arg != "text":
                if arg != "show" and arg != "complete":
                    step[arg] = subblock.string()
                else:
                    subblock.match("if")
                    step[arg + " if"] = subblock.rest()
            else:
                if subblock.has_block():
                    sub = subblock.subblock_lexer()

                    while sub.advance():
                        step["text"].append(quest_step_text_parse(sub))

                else:
                    step["text"].append(quest_step_text_parse(subblock))

        return step

    def quest_step_text_parse(sub):

        text = {"text":"","condition":"True"}

        text["text"] = "\""+sub.string()+"\""

        if sub.match("if"):
            text["condition"] = sub.rest()

        return text

    def quest_execute(parsed):

        quests.append(Quest_( parsed))

    renpy.register_statement("quest",parse = quest_parse, execute = quest_execute, block = True)
    renpy.register_statement("quest_with_parts",parse = quest_with_part_parse, execute = quest_execute, block = True)
