def get_InventorySlot(
        d):  # check if an item is in the inventory (and get slot)

    # Accepts: d MUST be an obj_id

    # CHECK (and return) object's inventory-slot
    if 'inventory-slot' in gD.gameDB['objectsDB'][d]:
        inv_slot = gD.gameDB['objectsDB'][d]['inventory-slot']

        # check if object is IN inv
        if d in gD.PLAYERINV[inv_slot]:
            return inv_slot
        else:
            return False

    else:
        # check if item can take GET, PUT or USE commands
        if any(k in gD.gameDB['objectsDB'][d]
               for k in ('getCmds-OK', 'putCmds-OK', 'useCmds-OK')):
            de.bug(5, "ERROR, missing inventory slot on ",
                   gD.gameDB['objectsDB'][d], "in gameData file")
        else:
            de.bug(5, "this object ", gD.gameDB['objectsDB'][d]['name'],
                   "cannot exist in the inventory")
            return False
def uiActions(cmd, obj, jun, via, inps, uiData):  # generic UI cmd handler

    # Resetting values
    my_cmd = None

    # check for singleton object with no command (show help if it is)
    if cmd != None:

        # consolidate cmd reference word
        my_cmd = gD.INPUT_VARS['THIS_CMD']['user-input']

    # render the appropriate user feedback message for the cmd
    if my_cmd in gD.gameDB['uiCmds']['playerCmds']:

        if my_cmd == "inv" or my_cmd == "inventory":

            renderers.render_charInventory()

    elif my_cmd in gD.gameDB['uiCmds']['generalCmds']:

        # Just print out the message for the UI command
        ctrls.printText(uiData[my_cmd], my_cmd)

    else:
        de.bug("Error (doCommand): command '", my_cmd, "' not found in uiCmds")
Exemplo n.º 3
0
def render_objectActions(d, cmd, t, ob=None):

    de.bug(3, "data for interaction is", d)

    if t in ("get-take", "put-leave", "ok", "unlocked"):
        print(ss.inputFeedbackPre, "You", cmd, "the", d['name'].lower())

    elif t == "has-req-obj":
        print(ss.inputFeedbackPre, "You", cmd, "the", d['name'].lower(),
              "with the", gD.gameDB['objectsDB'][ob]['name'].lower())

    elif t == "use":  # singleton "use" command: use on what?
        print(ss.inputFeedbackPre, "Use the", d['name'].lower(), "to do what?")

    elif t == "locked_by":  # tell player what req obj is
        print(
            ss.inputFeedbackPre, "The", d['name'].lower(), "is locked by the",
            gD.gameDB['objectsDB'][d['permissions']
                                   ['locked_by']]['name'].lower())

    elif t == "unlocked_by":  # tell player what req obj is
        print(
            ss.inputFeedbackPre, "The", d['name'].lower(),
            "can be locked using the", gD.gameDB['objectsDB'][
                d['permissions']['unlocked_by']]['name'].lower())

    elif t == "illegal":  # user tried to do an illegal action on an object
        print(ss.inputFeedbackPre, "You can\'t", cmd, "the", d['name'].lower())
def get_ObjectContents(obj_id):

    # get contents of an objects. Returns [ids, descs, type-of-containment]
    obj = gD.gameDB['objectsDB'][obj_id]

    # check this obj actually HAS children
    if 'contains' in obj['state']:

        # required access check
        if get_ObjectPermissions(obj) != 'locked':

            # reset type
            t = False

            # make array of contained obj refs
            cont_objs_ids = []
            cont_objs = []

            # Determine if contained objects are "in" or "via" their container
            # makes a "mixed bag" of descriptions if there are multiple types
            # type inherits from the last item in the list
            # could be changed to make it smarter if we need that functionality
            for o in obj['state']['contains']:
                cont_objs_ids.append(o)

                if o[0:2] == "ob":
                    cont_objs.append(gD.gameDB['objectsDB'][o]['name'])
                    t = "in"

                elif o[0] == "m":
                    for i, j in gD.gameDB['moveCommandsDB'][o].items():
                        cont_objs.append(j['moveDesc'])
                    t = "via"

            # return a list [ids, obs, t] == ids, descriptions, type
            return [cont_objs_ids, cont_objs, t]

        else:

            de.bug(6, "Cannot access object:", obj_id)
            return obj_id, False, False

    else:

        de.bug(6, "Object:", obj_id, "has no contents")
        return obj_id, False, False
def update_WorldState(ids, t, c):

    # change the World State e.g. objects in the world: add, remove etc.

    de.bug(1, "update World State with", ids, " ", t, "and", c)

    # == REMOVE OBJECTS ==============================

    if c == 'remove':

        if t == False:  # sent obj has no contents

            if ids in gD.locDB[gD.CURRENT_LOC]['locObjects']:
                gD.locDB[gD.CURRENT_LOC]['locObjects'].remove(ids)

        else:

            for ob in ids:
                if t == "in":
                    if ob in gD.locDB[gD.CURRENT_LOC]['locObjects']:
                        gD.locDB[gD.CURRENT_LOC]['locObjects'].remove(ob)
                elif t == "via":
                    if ob in gD.LOCDATA['moveCmds']:
                        gD.LOCDATA['moveCmds'].remove(ob)

    # == ADDING OBJECTS ==============================

    elif c == 'add':

        if t == False:  # sent obj has no contents

            if ids not in gD.locDB[gD.CURRENT_LOC]['locObjects']:
                gD.locDB[gD.CURRENT_LOC]['locObjects'].append(ids)

        else:

            for ob in ids:
                if t == "in":
                    # add contained objects to locdata objects list
                    if ob not in gD.LOCDATA['locObjects']:
                        gD.LOCDATA['locObjects'].append(ob)

                elif t == "via":
                    if ob not in gD.LOCDATA['moveCmds']:
                        gD.LOCDATA['moveCmds'].append(ob)
def throwError(s, dd):
    de.bug("we are in throwError() with this data: ", dd)
    # error types and data truths
    theTruth = {'uiSpawn': gD.gameDB['uiCmds']}

    # throw an error of source s
    if s in theTruth:
        # expect data d
        for i, j in theTruth.items():
            d = j
        # but got data dd
        if d != dd:
            # show error message plus data mismatch
            print(ss.errorPre + "Data mismatch")
            print(ss.errorPre + "Expect data: '", d, "' but received data: '",
                  dd, "'")
        else:
            print(ss.errorPre + "No error found...")
    # error source not recognised
    else:
        print(ss.errorPre + "Error source '", s, "' not recognised")
def get_ObjectPermissions(d):  # access control to certain objects

    # Accepts: d = whole object
    # Returns:
    # "ok" if no access restrictions on object
    # "has-req-obj" if player has req_obj to access locked object
    # "locked_by" or "unlocked_by" if access is denied

    perm_ok = False

    # check the state of the object (locked etc)
    if 'access' in d['state']:

        if d['state']['access'] == 'locked':
            perm_type = "locked_by"
        elif d['state']['access'] == 'unlocked':
            perm_type = "unlocked_by"

        if perm_type in d['permissions']:
            req_obj = d['permissions'][perm_type]

            # check if player has required object in their inventory
            de.bug(5, "checking player inventory for", req_obj)

            if get_InventorySlot(req_obj):
                perm_ok = True

        if perm_ok == True:
            # player has the req obj
            return "has-req-obj"
        else:
            # player does NOT have req obj, just return state
            return perm_type

    else:
        # no restrictions so return "ok" (not True, or it overrides every other condition check!)
        return "ok"
Exemplo n.º 8
0
def cmdDidYouMeanThis(tks, parsed_list): # check with player what input actually was
    
    # flatten out parsed_cmds because we don't need it segmented by token
    pdl = {}
    for a, b in parsed_list.items():
        for c, d in b.items():
            pdl[c] = d
    
    de.bug(1, "Original parsed_list", parsed_list, "vs flatten pdl list", pdl)
    
    # get first 'cmd' in parsed_list of cmds
    c_lst = [a for a, b in pdl.items()]
    
    # handle empty c_lst - which could mean that the input was NONE
    # i.e. player probably just pressed RETURN
    if len(c_lst) > 0:
        # get an integer for every n+-cmd keys in parsed list
        c_pos = c_lst[0][0]
        c_pos = int(c_pos) - 1
        
        # grab all junk words to let user know they are unrecognised
        unknown_junk = ''
        for i in tks[:c_pos]:
            unknown_junk += str(i)
            if tks.index(i) < len(tks[:c_pos]) - 1:
                unknown_junk += ' '
            
        # remove all (junk word) tokens from inputTokenized list that appear 
        # before the first valid parsed_cmd     
        new_tokens = tks[c_pos:]
        user_conf = ' '.join(new_tokens)
        
        # return sanitised input and setup confirmation request prompt
        de.bug(1, "3. confirm me this", user_conf)
        gD.PROMPT = 'reqconf'
        gD.USERCONF = user_conf
        gD.UNKNOWN_INPUT = unknown_junk
        
    else: # just spawn default PROMPT again
        
        de.bug(1, "no input, just respawn default PROMPT")
        gD.PROMPT = False
        gD.USERCONF = None
        gD.UNKNOWN_INPUT = None
Exemplo n.º 9
0
import debugger as de
import gameData as gD
import settings as ss
import controllers
import input_parsing as parseInp
import command_handling as doCmd
import errorHandler


# == INITIALISE GAME DATA == ####################################

# initialise GLOBALS
gD.init()

de.bug(1, "allInputRefs", gD.allInputRefs)



# == RENDER FIRST/DEFAULT LOCATION == #############################

# render first/default location
loc = gD.DEFAULTLOC
controllers.changeLoc(loc)

###################################################################
# GAME STATE PLAYING LOOP 
###################################################################


WIN = False
Exemplo n.º 10
0
def cmdLengthChecker(cmd_mtch, parsed_cmds, tkns):

    # verify that the input contains the right number of 
    # cmd words to complete a valid command phrase
    
    if type(cmd_mtch) == list:
        
        # If the object to be checked is a list (not a set{})
        # then it is a singleton and we only need to find the commands 
        # in the list that only have ONE word and then check if the 
        # tokenised single word player input and any of those commands 
        # match exactly
        
        de.bug(1, "singleton command, checking for length=1 valid commands in", cmd_mtch)
                
        for rf in cmd_mtch:
            rf_elems = rf.split("-")
            
            # find the appropriate cmd_list in allInputRefs
            for a, b in gD.allInputRefs.items():
                if rf_elems[0] == a:
                    cmd_wrds = b[int(rf_elems[1])]
                        
            # count the number of words in the command
            cmd_wrds_len = len(tokenizeInput(cmd_wrds))
            
            # we are only interested in one word commands               
            if cmd_wrds_len == 1:
                # does the player input match any single command word?
                for t in tkns:
                    if t == cmd_wrds:
                        de.bug(1, "valid command phrase matched:", t, "as", cmd_wrds, "returning ref", rf)
                        return rf
                
        return False
            
    else:
        # if cmd_match is not a list then check each item in the set
        # to see if they share a multi-word command
        
        de.bug(1, "Checking command length")
        
        for cmd_item in cmd_mtch:
            
            # get the actual command-tokened words
            cmd_elems = cmd_item.split("-")
            
            # handle each of the types of command
            if (cmd_elems[0] == 'o') or (cmd_elems[0] == 'm'):
              cmd_lst = gD.allInputRefs[cmd_elems[0]]
            else:
             cmd_lst = gD.gameDB['actionCmds'][cmd_elems[0]]
            
            if cmd_elems[0] == 'o':
                suf = "-obj"
            elif cmd_elems[0] == 'm':
                suf = "-mov"
            elif cmd_elems[0] == 'conJuncts':
                suf = "-jun"
            else:
                suf = "-cmd"
            
            # count the number of words
            cmd_wrds = cmd_lst[int(cmd_elems[1])]
            cmd_len = len(tokenizeInput(cmd_wrds))
            de.bug(1, "cmd wrds '", cmd_wrds, "' cmd len", cmd_len)
            
            # require this many sequential parsed_cmds.keys() matches
            q = 1
            cmd_valid = True
            while q <= cmd_len:
                
                # increment through each "n-suffix"
                myKey = str(q) + suf
                de.bug(1, "check this key", myKey)
                
                #check we haven't just run out of cmds
                if myKey in parsed_cmds.keys():
                    
                    if cmd_item not in parsed_cmds[myKey]:
                        de.bug(1, "missing in", myKey)
                        cmd_valid = False
                
                else: # failed to match full length, invalid command
                    
                    cmd_valid = False
            
                q = q + 1
                
            # if yes, this is a valid command
            if cmd_valid == True:
                
                de.bug(1, "valid command phrase matched:", cmd_wrds, "as", cmd_item)
                return cmd_item
                
                # no need to check further cmd_items
                break
Exemplo n.º 11
0
def parseInput(skip=False): # extract objects from tokenized input
    
    # Reset duplicates prompt builder before next input parsing run    
    if gD.PROMPT == 'duplicates':
        gD.PROMPT = False
    
    tkns = gD.TOKENS
    
    # 'skip' = Setup for "reSTART" of parseInput see: re_runWrdChecker(d)
    # to avoid over-writing existing parsed_cmds etc. on 2nd run
    
    if skip == False:
        
        parsed_cmds = {}
        matched_cmds = None
        type_track = []
        
        i = 0      # cmd-type index dictKey
        
        # for each word in the input
        for w in tkns:
            
            # use each WORD token to create GROUPS of parsed cmd matches
            parsed_cmds[w] = {}
            
            i = i + 1
            
            # check against every type of input and parse 
            # out useful references for handling back in gameExec  
            
            for j, k in gD.allInputRefs.items(): # used to be legalinputs.items()
                # for each cmd in each cmd group
                for l in k:
                    # is the word in the cmd group
                    if re.search(w, l):
                        
                        # complex bit: if the type of command changes
                        # between m, o, and c for the SAME word in tkns
                        # artificially bump i to avoid duplicate index numbers
                        type_track.append(j)
                        if len(type_track) > 1:
                            # match back for 'm'
                            if type_track[len(type_track)-1] == 'm':
                                if type_track[len(type_track)-2] != 'm':
                                    i = i + 1
                            # match back for 'o'                           
                            if type_track[len(type_track)-1] == 'o':
                                if type_track[len(type_track)-2] != 'o':
                                    i = i + 1
                            # match back for 'c'                           
                            if type_track[len(type_track)-1] == 'c':
                                if type_track[len(type_track)-2] != 'c':
                                    i = i + 1
                            # match back for neither 'm' or 'o' or 'c'
                            if type_track[len(type_track)-1] != 'o':
                                if type_track[len(type_track)-1] != 'm':
                                    if type_track[len(type_track)-1] != 'c':
                                        if type_track[len(type_track)-2] == 'o' or type_track[len(type_track)-2] == 'm' or type_track[len(type_track)-2] == 'c':
                                            i = i + 1
                         
                        # handle each of the command types
                        # because move and object don't have
                        # explicit labels for j, unlike cmds
                        if j == "m":
                            c = "mov"
                        elif j == "o":
                            c = "obj"
                        elif j == "conJuncts":
                            c = "jun"
                        else:
                            c = "cmd"
                        
                        # combine cmdgrp name - match index as label
                        c = str(i) + '-' + c
    
                        # combine j and the index of k as valid
                        # matching cmds
                        
                        ind = j + "-" + str(k.index(l))
                        
                        # build list of potential cmd matches
                        # called PARSED_CMDS
                        
                        if c in parsed_cmds[w].keys():
                            parsed_cmds[w][c].append(ind)
                        else:
                            parsed_cmds[w][c] = [ind]
            
            
    else:
        
        parsed_cmds = skip
        
    de.bug(1, "Parsed input: tokens", tkns, "and cmds", parsed_cmds)

    ## Check output from above: "parsed_cmds" using wrdChecker and RETURN    
    if len(parsed_cmds) > 0:
        matched_cmds = wrdChecker(tkns, parsed_cmds)
    
    if matched_cmds == False:
        de.bug(1, "USERCONF", gD.USERCONF)
        de.bug(1, "PROMPT", gD.PROMPT)
        de.bug(1, "UNKNOWN JUNK", gD.UNKNOWN_INPUT)
        matched_cmds = [None, None, None, None]
        
    elif matched_cmds != None:
        de.bug(1, "successfully matched these commands", matched_cmds)
        
    else:
        matched_cmds = [None, None, None, None]
        de.bug(1, "there were no valid commands matched in the input")
    
    # RETURN all of the things!!
    return matched_cmds
Exemplo n.º 12
0
def wrdChecker(tkns, parsed_cmds):
    
    # If the first dict group in parsed_cmds has nothing in it
    # the first token did not match and so is probably junk
    # check with the player what they really wanted to do first
    # and automatically resend commands if correct to do so
    
    junk_wrds = False
            
    if len(parsed_cmds[tkns[0]]) < 1:
        de.bug(1, "First token", "'"+tkns[0]+"'", "not a valid input. Check for junk input.")
        junk_wrds = True
    
    # handle finding junk words (above) or second pass as a "reqconf"
    if junk_wrds == True or gD.PROMPT == 'reqconf':
        
        if gD.PROMPT == False:
            cmdDidYouMeanThis(tkns, parsed_cmds)
            # return matched_cmds as False to parseInput()
            return False
        
        elif gD.PROMPT == 'reqconf': # require Y/N confirmation
            
            if tkns[0].lower() == "y": # if y or Y entered
                gD.PROMPT = 'autoresend'
                
            else: # if anything else treat it as a NO (bcoz 'n' = 'north')
                gD.USERCONF = None
                gD.PROMPT = False
                gD.UNKNOWN_INPUT = None
            
            # return matched_cmds as False to parseInput()
            return False
            
    else: # check parsed_cmds as normal
        
        # use tkns as a reference, because parsed_cmds dict is unordered
        # check if each parsed_cmds[tkns] shares any commands with another
        tkn_cmd_matches = {} # complete list of input tokens & matched cmds
        known_cmds = []
        parsed_final = [] # to send back to gameExec

        # skip this if we are dealing with single word input
        if len(tkns) > 1: 
            
            # make a working copy, so we can amend it later
            working_tokens = tkns 
            i = 0
            
            # step through tkns as a guide list
            for current_token in working_tokens: 
                
                # Deal with tokens that have MULTIPLE matches in gameData first
                if len(parsed_cmds[current_token]) > 1:
                    
                    de.bug(1, "Multiple possible gameData matches found for", parsed_cmds[current_token])
                    
                    # if existing tkn_cmd_matches contain get, put, int or useCmds
                    del_keys = []
                    for v in tkn_cmd_matches.values():
                        if ('getCmds' in v) or ('putCmds' in v) or ('intCmds' in v) or ('useCmds' in v):
                        
                            de.bug(1, "OBJECT command already found, forcing object discovery")
                            for a, b in parsed_cmds[current_token].items():
                                de.bug(1, "Find 'o-' in", b)
                                for c in b:
                                    if 'o-' not in c:
                                        del_keys.append(a)
                                    
                            de.bug(1, "del_keys", del_keys)
                            for d in del_keys:
                                del parsed_cmds[current_token][d]
                                
                            de.bug(1, "Cleaned PARSED_CMDS", parsed_cmds[current_token])
                            
                            parsed_final = re_runWrdChecker(parsed_cmds)
                            de.bug(1, "PARSED_FINAL (after reSTART)", parsed_final)

                            return parsed_final
                        
                        # otherwise return a "duplicate objects found" response
                        else:
                            
                            # THIS IS INCOMPLETE, but it is hard to create a situation 
                            # where this specific disambiguation would be needed
                            de.bug(1, "Which of these did you mean for", current_token, "?")
                            
                    
                # Otherwise check for MULTI word commands in the input
                else:
                    
                    de.bug(1, "Current token is", working_tokens[i])
                    
                    # if we are not at the last item in parsed_cmds
                    if len(working_tokens) > working_tokens.index(current_token)+1:
                        
                        # reset some vars
                        shared_cmds = []
                        next_token = working_tokens[i+1]
                        
                        # compare the commands for this parsed_cmds(key)
                        # with the "next token" according to working_tokens
                        for a, b in parsed_cmds[current_token].items():
                            for cm in b:
                                shared_cmds.append(cm)
                                    
                        for a, b in parsed_cmds[next_token].items():
                            for cm in b:
                                shared_cmds.append(cm)
                                
                        de.bug(1, "ALL FOUND cmds", shared_cmds)
                    
                        # check shared_cmds for duplicates
                        dupe_found = False
                        dupe_cmds = []
                        for c in shared_cmds:
                            if shared_cmds.count(c) > 1:
                                dupe_cmds.append(c)
                                dupe_found = True
                                
                        # if so combine current + next tokens in our working_tokens list
                        if dupe_found == True:
                            
                            de.bug(1, "Duplicates found", dupe_cmds)
                            
                            # update working_token list so the index is still accurate
                            working_tokens[i] = current_token +" "+ next_token
                            del working_tokens[i+1]
                            
                            de.bug(1, "AMENDED working_tokens", working_tokens)
                            
                            # check if the combined tokens match a command 
                            # and if so append to our final dict of matches
                            if len(dupe_cmds) > 2:
                                de.bug(1, "TOO MANY duplicate commands found for", dupe_cmds)
                            
                            cmd_elms = dupe_cmds[0].split("-")
                            if working_tokens[i] == gD.allInputRefs[cmd_elms[0]][int(cmd_elms[1])]:
                                de.bug(1, "this command is", dupe_cmds[0])
                                
                                tkn_cmd_matches[working_tokens[i]] = dupe_cmds[0]
                                
                            else:
                                
                                de.bug(1, "We have a weird problem with this input", working_tokens[i], "it doesn't resolve to one single command in gameData")
                            
                        
                        # If no dupes, this is a SINGLE word command
                        else:
                            
                            # check it's not a malformed multi-word
                            de.bug(1, "single word command detected")
                            for x, y in parsed_cmds[current_token].items():
                                valid = cmdLengthChecker(y, parsed_cmds[current_token].items(), tkns)
                                if valid != False:
                                    de.bug(1, "This came back as VALID:", valid)
                                    
                                    tkn_cmd_matches[working_tokens[i]] = valid
                                else: 
                                    de.bug("that wasn't a fully formed command, ignoring it")
                                    
                        
                        de.bug(1, "MATCHED COMMANDS so far (single word)", tkn_cmd_matches)
                        
                        # bump the i cursor and keep going (because we combined two items
                        # we just need to check the next item, as normal)
                        i = i + 1

                            
                    else:
                        
                        de.bug(1, "Got to final word in working_tokens")
                        
                        # if we know we are matching a single word then 
                        # it can match exactly and it will be correct
                        
                        for a, b in parsed_cmds[current_token].items():
                            for cc in b:
                            
                                cmd_elms = cc.split("-")
                                if working_tokens[i] == gD.allInputRefs[cmd_elms[0]][int(cmd_elms[1])]:
                            
                                    de.bug(1, "this command is", cc)
                                    
                                    tkn_cmd_matches[working_tokens[i]] = cc
                                    
                                    de.bug(1, "MATCHED COMMANDS so far (final word)", tkn_cmd_matches)
                                    
                                    break
                                    
                                else:
                                    
                                    de.bug(1, "We have a weird problem with this input", working_tokens[i], "it doesn't resolve to one single command in gameData")

                    
        # This is a SINGLE word input
        else:
            
            # check it's not a malformed multi-word
            de.bug(1, "single word input detected")
            
            # NOTE: If an input has multiple possible entries 
            # in the gameData it will send off the cmdLengthChecker for 
            # each one in the for loop here below. 
            
            valid_singles = [] 
            for x, y in parsed_cmds[tkns[0]].items():
                valid = cmdLengthChecker(y, parsed_cmds[tkns[0]].items(), tkns)
                if valid != False:
                    de.bug(1, "This came back as VALID:", valid)
                    
                    # So... We need to collect all possible matches
                    valid_singles.append(valid)

                else: 
                    de.bug("that wasn't a fully formed command, ignoring it")
            
            # Then ignore the objects / conjuncts because this is 
            # a single command, so more likely to be a movement/command
            if len(valid_singles) > 1:
                
                de.bug(1, "Most likely is a single COMMAND, deleting matched objects etc.")
                del_keys = []
                for c in valid_singles:
                     if 'o-' in c:
                         del_keys.append(c)
                        
                de.bug(1, "del_keys", del_keys)
                for d in del_keys:
                    valid_singles.remove(d)
                    
                de.bug(1, "Cleaned VALID SINGLES", valid_singles)
                
            # If only ONE VALID match, all is fine, keep going
            if len(valid_singles) == 1:
                tkn_cmd_matches[tkns[0]] = valid_singles[0]
                
            else: # final check just in case
                
                #### NEED TO FIX THIS WITH A PROPER ERROR RESPONSE!! ####
                de.bug("ERROR!!!!! can't resolve this command. Too many gameData matches!!!")
                
        
        de.bug(1, "MATCHED COMMANDS so far (all done)", tkn_cmd_matches)        
        de.bug(1, "CHECK parsed_final = ", parsed_final)
        
        ## Finally, classify the known commands    
        for a, b in tkn_cmd_matches.items():
            
            known_cmds.append(b)
        
        de.bug(1, "ALL KNOWN COMMANDS, in order", known_cmds)        
        
        # then classify each matched cmd as a type
        # o = obj, m = mov, conJunct = con 
        # else = cmd
        a_cmd = None
        a_obj = None
        a_conJunct = None
        a_via = None
        obj_ls = []
        type_list = [None, None, None, None] # see grammar bit below
        
        for i in known_cmds:
            els = i.split("-")
            if els[0] == "conJuncts":
                a_conJunct = i
                type_list[known_cmds.index(i)] = 'jun'
            elif els[0] == "o":
                # obj and via present
                obj_ls.append(i)
                type_list[known_cmds.index(i)] = 'obj'
            else:
                a_cmd = i
                type_list[known_cmds.index(i)] = 'cmd'
                
        
        de.bug(1, "type_list", type_list)
        
        # assign obj and via, if present                
        if len(obj_ls) > 1:
            a_obj, a_via = obj_ls
        elif len(obj_ls) == 1:
            a_obj = obj_ls[0]
        
        
        # build and return the correctly ordered variables to gameExec
        parsed_types = ['cmd', 'obj', 'jun', 'via']
        parsed_final.extend([a_cmd, a_obj, a_conJunct, a_via])
        
        # Create TEMP_VARS dictionary of all user-input, dicovered matches
        # in gameData, and locations of objects for subsequent NLP rules
        
        TEMP_VARS = {} 
        
        for a, b in tkn_cmd_matches.items():
            v_name = ('this_' + parsed_types[parsed_final.index(b)]).upper()
            TEMP_VARS[v_name] = {}
            TEMP_VARS[v_name]['user-input'] = a
            TEMP_VARS[v_name]['ref-id'] = []
            if (parsed_types[parsed_final.index(b)] == 'obj') or (parsed_types[parsed_final.index(b)] == 'via'):
                TEMP_VARS[v_name]['obj-loc'] = []
                objIds = ctrls.get_ObjectId(a)
                de.bug(1, "possible ids for the obj are:", objIds)
                i = 0
                for o in objIds:
                    l = ctrls.get_ObjectLocation(o)
                    de.bug(1, "OBJ LOC is", l)
                    TEMP_VARS[v_name]['obj-loc'].append(l)
                    if l == False: # FALSE if obj not found at loc or INV
                        TEMP_VARS[v_name]['ref-id'].append(False)
                    else:
                        TEMP_VARS[v_name]['ref-id'].append(o)
                    i += 1
                    
            else:
                TEMP_VARS[v_name]['ref-id'].append(b)
        
        de.bug(1, "TEMP_VARS", TEMP_VARS)
        
        # HANDLING MULITPLE MATCHES from vague user-input
        # Help the player by removing some options that are 
        # impossible given the structure of the user input 
        
        ##################### GRAMMAR BIT #############################
        ################### IMPORTANT NOTE ############################
        
        # This is only to remove impossible options from a list
        # that already contains too many options. This is NOT
        # pre-censoring user-input. All SINGLE matches, including illegal 
        # ones are handled later by specific clauses in command_handling
        
        # Remove INVALID Commands options
        if 'THIS_CMD' in TEMP_VARS:
            if len(TEMP_VARS['THIS_CMD']['ref-id']) > 1:
                
                # if OBJ present cannot be an EXPLORE command
                del_list = []
                if len(TEMP_VARS['THIS_OBJ']['ref-id']) > 0:
                    for i in TEMP_VARS['THIS_CMD']['ref-id']:
                        if "explore" in i:
                            c = TEMP_VARS['THIS_CMD']['ref-id'].index(i)
                            de.bug(1, "Need to REMOVE this ref-id", c)
                            del_list.append(c)
                            
                # de-dupe del_list
                del_list = list(set(del_list))
                # delete invalid items
                for d in del_list:
                    TEMP_VARS['THIS_CMD']['ref-id'].remove(d)
                            
                # If no OBJ, or OBJ not in INV, can't be a PUT command
                    # Not complete (because I think it is impossible 
                    # to have multiple matched commands, so this section is 
                    # not needed! :)
            
        # Remove INVALID Objects options
        if 'THIS_OBJ' in TEMP_VARS:
            if len(TEMP_VARS['THIS_OBJ']['ref-id']) > 1:
            
                ## RULE: if THIS_CMD is GET then....
                del_list = []
                for i in TEMP_VARS['THIS_CMD']['ref-id']:
                    if "get" in i:
                        
                        # ...object must be in LOCDATA or it is not visible to the player
                        for k in TEMP_VARS['THIS_OBJ']['ref-id']:
                            if k in gD.LOCDATA['locObjects']: # check locObjects, not ['obj-loc'] because a key in an OPEN box will be in locObjects, but have an obj-loc of the box
                                continue
                            else:
                                de.bug(1, "Need to REMOVE this ref-id", k, "and this obj-loc", TEMP_VARS['THIS_OBJ']['obj-loc'][TEMP_VARS['THIS_OBJ']['ref-id'].index(k)])
                                del_list.append(k)
                        
                        # ...the object cannot be in INV
                        for j in TEMP_VARS['THIS_OBJ']['obj-loc']:
                            if j == '$INV':
                                c = TEMP_VARS['THIS_OBJ']['obj-loc'].index(j)
                                de.bug(1, "Need to REMOVE this ref-id", TEMP_VARS['THIS_OBJ']['ref-id'][c], "and this obj-loc", TEMP_VARS['THIS_OBJ']['obj-loc'][c])
                                del_list.append(TEMP_VARS['THIS_OBJ']['ref-id'][c])
                
                # de-dupe del_list
                del_list = list(set(del_list))
                # delete invalid items
                for d in del_list:                                
                    TEMP_VARS['THIS_OBJ']['obj-loc'].remove(TEMP_VARS['THIS_OBJ']['obj-loc'][TEMP_VARS['THIS_OBJ']['ref-id'].index(d)])
                    TEMP_VARS['THIS_OBJ']['ref-id'].remove(d)            
                
                
                ## RULE: if THIS_CMD is PUT then...
                del_list = []
                for i in TEMP_VARS['THIS_CMD']['ref-id']:
                    if "put" in i:
                        
                        # ...the object must be in INV
                        for j in TEMP_VARS['THIS_OBJ']['obj-loc']:
                            if j != '$INV':
                                c = TEMP_VARS['THIS_OBJ']['obj-loc'].index(j)
                                de.bug(1, "Need to REMOVE this ref-id", TEMP_VARS['THIS_OBJ']['ref-id'][c], "and this obj-loc", TEMP_VARS['THIS_OBJ']['obj-loc'][c])
                                del_list.append(TEMP_VARS['THIS_OBJ']['ref-id'][c])
                
                # delete invalid items
                for d in del_list:                                
                    TEMP_VARS['THIS_OBJ']['obj-loc'].remove(TEMP_VARS['THIS_OBJ']['obj-loc'][TEMP_VARS['THIS_OBJ']['ref-id'].index(d)])
                    TEMP_VARS['THIS_OBJ']['ref-id'].remove(d)   
                        
                
                ## RULE: check OBJ commands, if THIS_CMD not there remove OBJ
                del_list = []
                for o in TEMP_VARS['THIS_OBJ']['ref-id']:
                    this_obj = gD.gameDB['objectsDB'][o]
                    ch_list = []
                    for k, v in this_obj.items():
                        #match any of "getCmds-OK, putCmds-OK" etc
                        if 'OK' in k:
                            els = k.split("-")
                            ch_list.append(els[0])
                    
                    cm = TEMP_VARS['THIS_CMD']['ref-id'][0].split("-")
                    if ch_list.count(cm[0]) == 0:
                        de.bug(1, "Need to REMOVE this ref-id", o, "and this obj-loc", TEMP_VARS['THIS_OBJ']['obj-loc'][TEMP_VARS['THIS_OBJ']['ref-id'].index(o)])
                        del_list.append(o)
                        
                # de-dupe del_list
                del_list = list(set(del_list))
                # delete invalid items
                for d in del_list:    
                    TEMP_VARS['THIS_OBJ']['obj-loc'].remove(TEMP_VARS['THIS_OBJ']['obj-loc'][TEMP_VARS['THIS_OBJ']['ref-id'].index(d)])
                    TEMP_VARS['THIS_OBJ']['ref-id'].remove(d)

        
        
        # Remove INVALID Conjuncts options
#        if 'THIS_JUN' in TEMP_VARS:
            # Not got any yet :)
        
        
        # Remove INVALID Vias options
        if 'THIS_VIA' in TEMP_VARS:
            if len(TEMP_VARS['THIS_VIA']['ref-id']) > 1:
                
                # RULE: if conjunct is "with", VIA must be in INV, or not valid
                del_list = []
                if TEMP_VARS['THIS_JUN']['user-input'] == 'with':
                    for l in TEMP_VARS['THIS_VIA']['obj-loc']:
                        if l is not '$INV':
                            de.bug(1, "Need to REMOVE this ref-id", TEMP_VARS['THIS_VIA']['ref-id'][TEMP_VARS['THIS_VIA']['obj-loc'].index(l)], "and this obj-loc", l)
                            del_list.append(TEMP_VARS['THIS_VIA']['ref-id'][TEMP_VARS['THIS_VIA']['obj-loc'].index(l)])
                            
                # delete invalid items
                for d in del_list:
                    TEMP_VARS['THIS_VIA']['obj-loc'].remove(TEMP_VARS['THIS_VIA']['obj-loc'][TEMP_VARS['THIS_VIA']['ref-id'].index(d)])
                    TEMP_VARS['THIS_VIA']['ref-id'].remove(d)
        
        
        
        ######################### END OF GRAMMAR BIT #######################
        
        
        de.bug(1, "CLEANED TEMP_VARS", TEMP_VARS)
        
        # set GLOBAL VARS
        gD.INPUT_VARS = TEMP_VARS
        de.bug(1, "INPUT_VARS are now:", gD.INPUT_VARS)
        
        # If more than one remaining option set input prompt to "duplicates"
        for i, j in gD.INPUT_VARS.items():
            if len(j['ref-id']) > 1:
                de.bug(1, "Duplicates still present. Need more details.")
                gD.PROMPT = 'duplicates'
                return False
        
        de.bug(1, "PARSED_FINAL (sending to gameExec)", parsed_final)
        
        return parsed_final 
Exemplo n.º 13
0
def re_runWrdChecker(d):
    de.bug(1, "!-!-!-! RESTARTING PARSEINPUT!!!")
    return parseInput(d)
Exemplo n.º 14
0
def render_Text(d, t="default"):  #generic text renderer

    if t == 'move':  # movement description text
        if d != False:
            print(ss.inputChangeLocPre, d)
        else:
            print(ss.inputFeedbackPre, "You can't go that way")

    elif t == 'win':  # winning message
        print(ss.inputFeedbackPre, d)

    elif t == 'exit':  #exit command
        print(ss.inputFeedbackPre, ss.exitMessage)


#    elif t == 'unlocked': # now open
#        print(ss.inputFeedbackPre, "The", d.lower(), "is now", t)

    elif t == 'already locked':  # now open
        print(ss.inputFeedbackPre, "The", d.lower(), "is", t)

    elif t == 'cheat':  #cheat command

        temp = 'this is t {}'.format(t)
        de.bug(temp)
        # show all available movement commands for this location
        print(ss.inputFeedbackPre, "Available moves are", end=": ")

        # unpack commands from nested dicts{}
        tmp = [j for i in d for j in i]

        # list the commands
        print(tfs.listify(tmp))

        #show custom cheater feedback message
        messages = ss.cheaterMessage
        print(ss.inputFeedbackPre,
              messages[random.randint(0,
                                      len(messages) - 1)])

    elif t == 'help':  #help command

        # split d - data payload in params
        genCmds = d[0]
        objCmds = d[1]

        # show all GENERAL commands for the game
        print(ss.inputFeedbackPre, "General commands",
              end=": ")  # end= prevents new line

        # unpack commands from nested dicts{}
        tmp = [j for i, k in genCmds.items() for j in k]

        # list the GENERAL commands
        print(tfs.listify(tmp))

        # show all OBJECT commands for the game
        print(ss.inputFeedbackPre, "Interaction commands",
              end=": ")  # end= prevents new line

        # retrieve commands in array data
        tmp = [i for i in objCmds]

        # list the OBJECT commands
        print(tfs.listify(tmp))

    elif t in ('look', 'search'):  #search command

        # show all objects in the location
        print(ss.inputFeedbackPre, "You find the following", end=": ")

        oRefs = [
            gD.gameDB['objectsDB'][i]['name'] for i in gD.LOCDATA['locObjects']
        ]
        #        for i in d:
        #            oRefs.append(gD.gameDB['objectsDB'][i]['name'])

        # list the object refs
        print(tfs.listify(oRefs, True))

        # show all monsters in the location!

        #TODO: Make search trigger all monsters revealed
        #### INCOMPLETE

    elif t in ('look for', 'where'):  # requires an obj [desc,location] array
        print(ss.inputFeedbackPre, "You see", d[0].lower(), d[1].lower())

    elif t == 'missing object':  # part of controllers.useObject()
        print(ss.inputFeedbackPre, "You can't see the", d.lower(), "here")

    elif t == 'look at':  # d is a list but [1] can be False is d has no access restrictions i.e. "locked"
        if (len(d) > 1) and (d[1] != False):
            print(ss.inputFeedbackPre, "You see", d[0].lower(), ". It is",
                  d[1].lower())
        else:
            print(ss.inputFeedbackPre, "You see", d[0].lower())

    elif t == 'not in inv':  # player trying to drop an obj not in their inv
        print(ss.inputFeedbackPre, "You do not have the", d.lower(),
              "in your inventory")

    elif t == 'already in inv':  # trying to add an obj already in the inv
        print(ss.inputFeedbackPre, "You already have the", d.lower(),
              "in your inventory")

    elif t == 'contained by':
        print(ss.inputFeedbackPre, "You see", tfs.listify(d[0], True),
              "in the", d[1].lower())

    elif t == 'container empty':
        print(ss.inputFeedbackPre, "The", d.lower(), "is empty!")

    elif t == 'seen through':
        print(ss.inputFeedbackPre, "You see", tfs.listify(d[0], True),
              "through the", d[1].lower())

    elif t == 'examine':  # part of controllers.useObject()

        # grab object name & remove from list
        oword = d.pop()

        print(ss.inputFeedbackPre, "You can",
              end=" ")  # end= prevents new line
        # list out the available commands
        print(tfs.listify(d, False, "or"), "the", oword.lower())

    elif t == 'default':  # just render payload
        print(d)
def doCommand(cmd, obj, jun, via, uiData):

    legalInputs = gD.LEGALINPUTS

    if cmd != None:

        # we only need to identify the TYPE of cmd
        # so we can action the correct function next
        cmd_spl = cmd.split("-")
        cmd_ky = cmd_spl[0]
        my_cmd = gD.INPUT_VARS['THIS_CMD']['user-input']

        de.bug(1, "my_cmd is", my_cmd)
        de.bug(1, "move cmds for this loc are", gD.LOCDATA['moveCmds'])

        if cmd_ky == "m":  # MOVEMENT command

            moveDesc = False
            moveDest = False
            for m in gD.LOCDATA['moveCmds']:
                for h, i in gD.gameDB['moveCommandsDB'][m].items():
                    for j in i['cmds']:
                        if my_cmd == j:
                            moveDesc = i['goDesc']

                            if 'destId' in i:
                                moveDest = i['destId']
                            else:
                                de.bug(
                                    "NOTICE: This cmd doesn't change our location"
                                )

            # show moveDesc feedback for moveCmd
            ctrls.printText(moveDesc, "move")

            # if associated locID for moveCmd - ctrls.changeLoc
            ctrls.changeLoc(moveDest)

        elif cmd_ky in gD.gameDB['uiCmds'].keys():  # UI command

            # send to uiActions to handle the UI command
            uiActions(cmd, obj, jun, via, legalInputs, uiData)

        elif cmd_ky in gD.gameDB['actionCmds'].keys():  # ACTION command

            de.bug(2, "locDATA", gD.LOCDATA)

            # send the cmd and the obj to useObject for more detailed handling
            useObject(cmd, obj, jun, via)

        else:  # Command not known

            de.bug("Error (doCommand): The command", cmd, "is not handled yet")

    elif obj != None:  # empty cmd but we have a singleton obj

        # send to useObject anyway to give Player object help feedback
        useObject(cmd, obj, jun, via)

    else:  # Too many params are None to do anything useful

        return False
def useObject(cmd, obj, jun, via):  # generic Object handler

    # E.G. cmd: generalCmds-0 | obj: o-7 | jun: conJuncts-2 | via: o-11

    ######### GOT TO HERE ###############

    # then finally
    # need to go through anything that REworks out any of
    # these now global references and make then use the
    # GLOBALS instead. For example: do_command()

    # THEN FINALLY need to make the "what am I" function
    # that "is this object at the location" can call
    # and tidy up that whole useObject function A LOT
    """
    INPUT_VARS are now: {
    'THIS_CMD': {'user-input': 'open', 'ref-id': ['intCmds-0']}, 
    'THIS_OBJ': {'user-input': 'box', 'ref-id': ['ob0002'], 'obj-loc': ['z0001']}, 
    'THIS_JUN': {'user-input': 'with', 'ref-id': ['conJuncts-0']}, 
    'THIS_VIA': {'user-input': 'key', 'ref-id': [], 'obj-loc': []}
    }
    """

    # Resetting values
    #    obs_list = gD.LOCDATA['locObjects']
    obj_cmds = []
    cmd_ref = None
    obj_ref = None
    via_ref = None
    jun_ref = None
    obj_id = None
    this_obj = None
    this_via = None

    # SETUP SCRIPT VARS from globals

    if cmd:
        cmd_ref = gD.INPUT_VARS['THIS_CMD']['user-input']

    if jun:
        jun_ref = gD.INPUT_VARS['THIS_JUN']['user-input']

    if via:
        via_ref = gD.INPUT_VARS['THIS_VIA']['user-input']

        # Detect invalid VIA
        if gD.INPUT_VARS['THIS_VIA']['ref-id']:
            via_id = gD.INPUT_VARS['THIS_VIA']['ref-id'][0]
            this_via = gD.gameDB['objectsDB'][via_id]
        else:
            de.bug(1, "INVALID VIA", via_ref)

    if obj:
        obj_ref = gD.INPUT_VARS['THIS_OBJ']['user-input']

        # Detect invalid obj
        if gD.INPUT_VARS['THIS_OBJ']['ref-id']:
            obj_id = gD.INPUT_VARS['THIS_OBJ']['ref-id'][0]
            obj_desc = gD.gameDB['objectsDB'][obj_id]['desc']
            obj_locdesc = gD.gameDB['objectsDB'][obj_id]['location']
            this_obj = gD.gameDB['objectsDB'][obj_id]

            # Get all Object Commands
            obj_cmds = ctrls.get_ObjectCommands(this_obj)

            # User referenced a VALID object WITHOUT putting
            # an action command - So give them help
            if cmd_ref == None:
                renderers.render_objectHelp(obj_cmds, this_obj['name'])
                return False  # exit this function
        else:
            de.bug(1, "INVALID OBJ", obj_ref)

    ############## COMMANDS THAT REQUIRE NO OBJECT ################

    if cmd_ref in gD.gameDB['actionCmds']['exploreCmds'] and obj == None:

        ### == generic explore COMMANDS: look / search etc ====

        # give user feedback on their command
        ctrls.printText(None, cmd_ref)
        return True  # exit this function, we're done here

    if via_ref:

        ### == navigation COMMANDS w/ VIA e.g. 'go in', 'get in' =========

        if cmd_ref in ('get', 'go', 'walk'):

            de.bug(3, "We have a VIA movement type of command!", cmd_ref, jun,
                   via)

            #TODO: Handle changing location with a cmd, jun, via input

            ######### NOT COMPLETE NEED RENDER TEXT TO HANDLE THIS ##
            # Needs to handle changing location using the via
            ########################################################

    ############## COMMANDS THAT NEED AN OBJECT ################

    if obj_ref:

        # if obj_ref != None, but gD.INPUT_VARS['THIS_OBJ']['ref-id'] == None:
        ## This means that the command is invalid for the object
        # so throw that error "You can't X the Y"
        if obj_id == None:
            de.bug(1, "INVALID obj", obj_ref, ". You can't", cmd_ref,
                   "this object")

        ### We are no longer checking if object at location before this
        # So GET for example, needs to check if INPUT_VARS['THIS_OBJ']['obj-loc'] == gD.CURRENTLOC
        # And put needs to check obj in INV
        # And any other cmd that requires obj to be local needs to CHECK

        ### == specific explore COMMANDS: look in / under etc ====

        if cmd_ref in gD.gameDB['actionCmds']['exploreCmds']:

            # check object access state
            ob_access = ctrls.get_ObjectState(this_obj, 'access')

            de.bug(4, "ob_access is:", ob_access)

            # GET the contained objects
            ids, descs, t = ctrls.get_ObjectContents(obj_id)

            ## check if object permissions prevent action
            if ob_access == "unlocked":

                # ADD the object to the world local objects
                ctrls.update_WorldState(obj_id, False, 'add')

                de.bug(1, "contained objects", descs)

                # full or empty container?
                if len(descs) > 0:
                    # feedback to player what they have discovered
                    ctrls.printText([descs, this_obj['name']], "contained by")
                else:
                    ctrls.printText(this_obj['name'], 'container empty')

            elif ob_access == "locked":

                # feedback to player about the req object
                renderers.render_objectActions(this_obj, cmd_ref, "locked_by")

                # does player have the req object?
                this_via_obj = gD.gameDB['objectsDB'][this_obj['permissions']
                                                      ['locked_by']]
                if ctrls.get_InventorySlot(this_via_obj) == False:
                    ctrls.printText(this_via_obj['name'], 'not in inv')

        ### == examine COMMANDS: look at, examine etc. =============

        elif cmd_ref in gD.gameDB['actionCmds']['examineCmds']:

            d = [this_obj['desc'], ctrls.get_ObjectState(this_obj, s='access')]

            ### FIX THIS #################
            # Combine these two printText renders into one

            # show object description
            ctrls.printText(d, 'look at')

            # bit of a hack this... add obj name to end of obj_cmds
            # for renderer to .pop() off afterwards
            obj_cmds.append(this_obj['name'])

            ctrls.printText(obj_cmds, 'examine')

        ### == search COMMANDS: look for, where etc ===========

        elif cmd_ref in gD.gameDB['actionCmds']['searchCmds']:

            # show both obj desc and loc together
            ctrls.printText([obj_desc, obj_locdesc], cmd_ref)

        ### == get, put, use, int COMMANDS =====================

        # check legal action for the object
        elif cmd_ref in obj_cmds:

            ### == get command add object to inventory ============

            # check all get aliases
            for i in gD.gameDB['actionCmds']['getCmds']:
                if cmd_ref == i:

                    # GET the contained objects
                    ids, descs, t = ctrls.get_ObjectContents(obj_id)

                    de.bug(4, "these contained objs", ids,
                           "this containment type", t, "this_obj", this_obj)

                    # add obj to inv & ctrls.update_WorldState
                    if ctrls.update_Inventory(obj_id, "add") != False:

                        # render feedback to player
                        renderers.render_objectActions(this_obj, cmd_ref,
                                                       "get-take")

                        # render the player inventory
                        renderers.render_charInventory()

                        # update child object state & get parent container
                        p = ctrls.update_ObjectState(obj_id, this_obj, cmd_ref)

                        # update parent container state using returned "p"
                        if p != None:

                            ctrls.update_ObjectState(obj_id, this_obj,
                                                     'un_contain', p)

                        # finally REMOVE the contained items from the world
                        # because they are now in player inventory
                        ctrls.update_WorldState(ids, t, 'remove')

                    else:

                        # trying to add obj ALREADY in inv
                        ctrls.printText(this_obj['name'], 'already in inv')

            ### == put command remove object from inventory =========

            #TODO: Need a more complex "put ... in... " version where this_obj
            # gets added to a new parent_container, not to local Objects
            # see 'get' above for handling parents vs local world objects

            # check all put aliases
            for i in gD.gameDB['actionCmds']['putCmds']:
                if cmd_ref == i:

                    # remove obj from inv
                    if ctrls.update_Inventory(obj_id, "remove") != False:

                        # is there a VIA object for the action?
                        if via != None:  # put something IN somewhere (VIA)

                            # update parent container (via) state
                            ctrls.update_ObjectState(obj_id, this_obj, 'add',
                                                     via_id)

                        else:  # simple put/drop command

                            # render feedback to player
                            renderers.render_objectActions(
                                this_obj, cmd_ref, "put-leave")

                        # ADD the object to the world local objects
                        ctrls.update_WorldState(obj_id, False, 'add')

                        # render the player inventory
                        renderers.render_charInventory()

                    else:

                        # trying to remove obj not in inv
                        ctrls.printText(this_obj['name'], 'not in inv')

            ### == open/unlock command do object custom action =============

            if cmd_ref in ("open", "unlock"):

                # check object access state
                ob_access = ctrls.get_ObjectState(this_obj, s='access')

                de.bug(4, "ob_access is:", ob_access)

                if ob_access == 'locked':

                    # check if object permissions prevent action
                    can_open = ctrls.get_ObjectPermissions(this_obj)
                    de.bug(4, "lock perms are", can_open)

                    if can_open in ("ok", "unlocked",
                                    "has-req-obj"):  # obj not locked

                        # render feedback to player
                        renderers.render_objectActions(
                            this_obj, cmd_ref, can_open,
                            this_obj['permissions']['locked_by'])

                        # update object state
                        ctrls.update_ObjectState(obj_id, this_obj, cmd_ref)

                    else:

                        # feedback access state of object to player
                        renderers.render_objectActions(this_obj, cmd_ref,
                                                       can_open)

                        # player does not have the req object
                        this_via = gD.gameDB['objectsDB'][obj_id][
                            'permissions']['locked_by']
                        if ctrls.get_InventorySlot(this_via) == False:
                            ctrls.printText(
                                gD.gameDB['objectsDB'][this_via]['name'],
                                'not in inv')

                else:

                    # not locked => can open: update object state
                    ctrls.update_ObjectState(obj_id, this_obj, cmd_ref)

            ### == close/lock command do object custom action =============

            elif cmd_ref in ("lock", "close"):

                # check object access state
                ob_access = ctrls.get_ObjectState(this_obj, s='access')
                de.bug(4, "ob_access is:", ob_access)

                if ob_access == 'unlocked':

                    # check if object permissions prevent action
                    can_close = ctrls.get_ObjectPermissions(this_obj)
                    de.bug(4, "lock perms are", can_close)

                    if can_close == "has-req-obj":

                        # render feedback to player
                        renderers.render_objectActions(
                            this_obj, cmd_ref, can_close,
                            this_obj['permissions']['unlocked_by'])

                        # update object state
                        ctrls.update_ObjectState(obj_id, this_obj, cmd_ref)

                    else:

                        # render object state feedback to player
                        renderers.render_objectActions(this_obj, cmd_ref,
                                                       can_close)

                        # player does not have the req object
                        this_via = gD.gameDB['objectsDB'][
                            this_obj['permissions']['unlocked_by']]
                        if ctrls.get_InventorySlot(this_via) == False:
                            ctrls.printText(this_via['name'], 'not in inv')

                else:

                    # feedback to player object already locked
                    ctrls.printText(this_obj['name'], 'already locked')

            ### == use command do object custom action =============

            elif cmd_ref == "use":

                # check used obj is in player inv
                if ctrls.get_InventorySlot(this_obj) != False:

                    # no target, singleton "use"
                    if via != None:

                        #TODO: The USE command and results of it

                        ## INCOMPLETE . JUST ALL OF THIS!!

                        # check object STATE
                        ctrls.update_ObjectState(obj_id, this_obj, cmd_ref)
                        de.bug("use key on -", via)
                        #use key on box

                        # renderers.render_objectActions(o, cmd, cmd)

                        # check correct req obj for obj

                        # do something now the obj is used
                        # for example a box display stuff inside

                    else:

                        # use key - "use key on what?"
                        # render feedback to player
                        renderers.render_objectActions(this_obj, cmd_ref,
                                                       cmd_ref)

                else:
                    # trying to use obj not in inv
                    ctrls.printText(this_obj['name'], 'not in inv')

        else:

            # must be an illegal command for this object
            # feedback 'you can't do that to this object'
            t = "illegal"
            renderers.render_objectActions(this_obj, cmd_ref, t)

    # IF ALL ELSE FAILS cmd is a singleton, show correct actionHelp feedback
    if cmd != None and obj == None and via == None:
        renderers.render_actionHelp(cmd_ref)
def update_ObjectState(obj_id, o, cmd_ref, p=None):

    # p is the parent container, optional param

    # reset values
    o_s = o['state']

    # == Simple state changes ==================================
    if cmd_ref == 'un_contain':

        de.bug(5, "Want to un-parent this:", obj_id, "from this:",
               gD.gameDB['objectsDB'][p]['state']['contains'])

        gD.gameDB['objectsDB'][p]['state']['contains'].remove(obj_id)

    elif cmd_ref == 'add':

        de.bug(5, "Adding", obj_id, "to", p)

        gD.gameDB['objectsDB'][p]['state']['contains'].append(obj_id)

    # == GET/PUT COMMANDS =============================================

    ## If object is contained, change its state to not-contained and
    # return the parent object for future processing

    elif cmd_ref in gD.gameDB['actionCmds']['getCmds']:

        if len(o_s):
            for s, t in o_s.items():

                if s == 'contained_by':

                    # get parent container
                    p = gD.gameDB['objectsDB'][obj_id]['state']['contained_by']

                    # remove contained by state as the object is now
                    # out of its container and into the world
                    del gD.gameDB['objectsDB'][obj_id]['state']['contained_by']

                    # return requirement to update parent container
                    return p

    # == OPEN/UNLOCK COMMANDS ==========================================

    elif cmd_ref in ('open', 'unlock'):  # open, unlock etc.

        if len(o_s):

            # change STATE and PERMISSIONS of object

            if 'access' in o_s:

                # RENAME the 'locked' state to 'unlocked'
                gD.gameDB['objectsDB'][obj_id]['state']['access'] = 'unlocked'

                # RENAME the permissions field
                # so a record of the locking item is kept (for re-locking)
                if 'locked_by' in o['permissions']:
                    gD.gameDB['objectsDB'][obj_id]['permissions'][
                        'unlocked_by'] = gD.gameDB['objectsDB'][obj_id][
                            'permissions']['locked_by']
                    del gD.gameDB['objectsDB'][obj_id]['permissions'][
                        'locked_by']

            de.bug(5, "changed state of", obj_id, "to",
                   gD.gameDB['objectsDB'][obj_id]['state']['access'], "and",
                   gD.gameDB['objectsDB'][obj_id]['permissions'])

            if 'contains' in o_s:

                # GET the contained objects
                ids, descs, t = get_ObjectContents(obj_id)

                # ADD the contained items to the game world
                update_WorldState(ids, t, 'add')

                # feedback to player the objects they have discovered
                if t == "in":
                    printText([descs, o['name']], "contained by")

                elif t == "via":
                    printText([descs, o['name']], "seen through")

    # == CLOSE/LOCK COMMANDS ==========================================

    elif cmd_ref in ('close', 'lock'):  # close, lock etc.

        if len(o_s):

            # have to do contents removal first, because otherwise
            # the box is locked and contents are inaccessible! :D

            if 'contains' in o_s:

                # GET the contained objects
                ids, descs, t = get_ObjectContents(obj_id)

                # ADD the contained items to the game world
                update_WorldState(ids, t, 'remove')

            if 'access' in o_s:

                # RENAME the 'unlocked' state to 'locked'
                gD.gameDB['objectsDB'][obj_id]['state']['access'] = 'locked'

                # RENAME the permissions field
                # so a record of the locking item is kept (for un-locking)
                if 'unlocked_by' in o['permissions']:
                    gD.gameDB['objectsDB'][obj_id]['permissions'][
                        'locked_by'] = gD.gameDB['objectsDB'][obj_id][
                            'permissions']['unlocked_by']
                    del gD.gameDB['objectsDB'][obj_id]['permissions'][
                        'unlocked_by']

            de.bug(5, "changed state of", obj_id, "to",
                   gD.gameDB['objectsDB'][obj_id]['state']['access'], "and",
                   gD.gameDB['objectsDB'][obj_id]['permissions'])