# File vw4.py # # Author: G.Doeben-Henisch # First date: Aug 7, 2019 # Last date: Aug 19, 2019 ################################################### # PY USING AAI PARADIGMA # APPLYING ACTOR-ACTOR STORY (AAS) and # ACTOR MODELING (AM) to the # VIRTUAL WORLD APPLICATION ################################################### ################################################### # SEE ACCOMPANYING VISUAL PRESENTATION # OF AAS AND AM INTERACTION ################################################### ################################################### # GENERAL OVERVIEW Level 0 ################################################## ''' As you can see in the accompanying diagram for the vw4.py source code there exists a hierarchy of AAS with AM(aA1) as a member and again an AAS embedded in AM(aA1) with AM(A) as a member. The first AAS at level 0 describes the interactions between the human user as an executing actor (eA) and a virtual world as an assisting actor (aA). Both actors are embedded in a communication relation COM. ''' ################################################### # GENERAL OVERVIEW Level -1 ################################################### ''' - The behavior function of the aA1 actor consists of two components: one component 'Com' interacts with the outside world AAS level 0, the other component 'Run' manages the internal 2D-space with its objects and their possible behavior in time. - The inner structure of the virtual world actor labeled aA1 allows the description of another actor-actor story (AAS) one level below 0 called level -1. This AAS is hidden from the outside of the virtual world actor 'aA1'. - This embedded AAS describes a 2-dimensional space SP with different kinds of objects. One kind of objects are the 'A'-labeled objects and a communication buffer CBF. The Run-function of the virtual world actor aA1 can read and write the communication buffere CBF and can thereby use information from the embedded actor A to organize the behavior of the 2D-space. By writing into the communication buffer CBF the virtual world actor aA1 can influence the behaviro of the embedded actor A. - One of the objects of the 2D-space -- the A-objects -- are again actors with assumed inputs and outputs. One can define an actor model for these actors which are elements of AAS level -1. - The in aA1 embedded actors A can receive messages from a communication buffer CBF within AAS level -1 and they can send messages to this communication buffer CBF. ''' ############################ # IMPORTS import random as rnd import copy as cp import vwmanager as vw ############################ # SUPPORTING FUNCTION # # Now in a dedicated module vwmanager.py in folder 'code' # Complete path: C:\Users\gerd_2\code # This path has to be included for the python path search mechanism # # Show actual path values # # >>> import sys #>>> sys.path # ... # Extend the python path by appending the modul path: # # In my case the path is as follows: # #>>> sys.path.append('C:\\Users\\gerd_2\\code') ########################## # Main Programm # ############### # MAIN # # The loop will work as long as the value of the variable 'loop' is different to 'N' # The loop represents the sequence of interactions between the user as executive actor and the virtual world as assisting actor. # # While running the loop the virtual world actor generates some internal data structures which then will be used for the management of an internal, # embedded actor-actor story on level -1. # # GLOBAL PROPERTIES OF SOME OBJECTS used in the 2D-space of the virtual world # objL={'F':[0,1000, 100], 'A':[0,1000,100,500,0]} ############################################# # The global objekt list objL contains properties for: # A food object 'F' which has an initial value of '1000' and can grow if below 1000 by 20 every cycle # An actor object 'A' which has an ID, an initial energy level of 1000, loses every cycle 200 energy units # independent of moving or not moving, and gains 500 energy units by eating # and a direction DIR=0 # These values will be attached to a new object generated in the 2D-space and can easily be changed for experimental reasons. ########################################### ''' The interactions in the AAS level 0 are the following ones: - The user will be asked from the virtual world actor: - how many 'Number of columns (= equal to rows!)' shall be realized - how large the 'Percentage (as integer) of obstacles in the 2D-grid' should be - how large the 'Percentage (as integer) of Energy Objects (= Food) in the 2D-grid' should be - how large ther 'Percentage (as integer) of Actor Objects in the 2D-grid' should be. - After this input the virtual world will generate a 2D-world with the entered dimensions and it is showing objects as 'O', food as 'F', spaces as '_', and actors as 'A'. - Then the user will be asked how man cycles (CYC) the world shall run. - If the number of wanted cycles (CYC) has been reached the user will be asked to stop the run (=N) or to continue (=Y). - During the preparation phase the following global data structure will be generated, which later in the loop will be used: - mx := the 2D-world matrix - plO := the list of all obstacle objects - olF := the list of all food objects - olA := the list of all actor objects ''' loop='Y' while loop!='N': ################################################################################### # ASKING USER FOR SOME PARAMETERS TO START ################################################################################## # Ask for mode of information given by the system # say = 1 asks for maximal information, say = 0 gives only minimal nformation say = int(input('Amount of information: 1 is maximum, 0 is minimum')) # Number of columns (m) and rows (n); by default equal. m=int(input('Number of columns (= equal to rows!) of 2D-grid ?')) n=m mx0=vw.nmlist(n) # Generate a first empty matrix n*m mx = cp.deepcopy(mx0) # Percentage % of obstacles in the 2D-world?\n) obstacles=int(input('Percentage (as integer) of obstacles in the 2D-grid?')) no=vw.numberObj(obstacles,n) mx=vw.placeObjs(no,n,mx,'O',say) # Percentage % of energy objects in the 2D-world?\n) energyObj=int(input('Percentage (as integer) of Food Objects in the 2D-grid ?')) no=vw.numberObj(energyObj,n) mx=vw.placeObjs(no,n,mx,'F',say) # Percentage % of actor objects in the 2D-world?\n) actorObj=int(input('Percentage (as integer) of Actor Objects in the 2D-grid ?')) no=vw.numberObj(actorObj,n) mx=vw.placeObjs(no,n,mx,'A',say) # List of actual obstacles in the grid c='O' olO=vw.makeobjL(c,objL,mx,n) name='obstacles' print('\n Objects as ',name,'\n') vw.printMX(olO) # List of actual food objects in the grid: c='F' olF=vw.makeobjL(c,objL,mx,n) name='food' print('\n Objects as ',name,'\n') vw.printMX(olF) # List of actual actor objects in the grid: c='A' olA=vw.makeobjL(c,objL,mx,n) name='actor' print('\n Objects as ',name,'\n') vw.printMX(olA) vw.printMX(mx) print('\n END OF PREPARATION\n') print('WORLD CYCLE STARTS\n') # Final computation of real percentages of objects # Because in the generation of new objects the already generated objects can be overwritten # these already existing ones can become diminished # 100% = n x n print('----------------------------------------------------') print('Real percentage of obstacles = ',len(olO)/((n*n)/100)) print('Real percentage of food = ',len(olF)/((n*n)/100)) print('Real percentage of actors = ',len(olA)/((n*n)/100)) print('----------------------------------------------------') ########################################################### # WORLD INTERNAL RUN STARTS # ########################################################## # COUNTING CYCLES (CYY) CYC=int(input('How many CYCLES do you want?')) stepMode = int(input('Single Step = 1 or Continous = 0?')) WCLCK=0 for t in range(CYC): print('Length of olA',len(olA)) if len(olA)<1: break # Show actual state of the GRID # All object lists (olO, olF, olA) will be read and visualized in a 2D-Grid # It is assumed that these lists represent the actual state of affairs. mx = vw.show2D(mx0, olO, olF, olA) print('\n-----------------------------------------------------\n') print('WORLD AT CYCLE = ',WCLCK,'\n') vw.printMX(mx) if stepMode == 1: cont = 'x' while cont != 'c': cont = input('Press key c for continuation!') # Generating new directions for move olA = vw.randDir(olA) if say == 1: print('New directions for actor objects:\n') vw.printMX(olA) else: pass # Compute positions in new virtual copy olAA from olA # The list olAA will be used to check wether the new positions are in agreement with the # 'laws' of the virtual world as managed by the actor model of the virtual world. # This checking proceeds in several individual steps. Every element whose planned # new position will be identified as 'not in agreement' will be replaced by the original # position (still available in the olA list) and marked with a '-1' direction. olAA=vw.newPos0s(olA,n,say) if say ==1: print('New positions for actor objects in olAA:\n') vw.printMX(olAA) print('Compare with old list olA \n') vw.printMX(olA) else: pass # Now starts a series of operations to eleiminate all impossible moves # In a first step it will be checked whether there is a collision between # the given objects and the new planned positions. # For this a DISALLOW-list will be generated for those actors which would cause collisions. disallowL = vw.reduceAOs(mx0,olO, olF, olAA,olA,say) # With the aid of disallowL will all the actors in olAA be replaced with # the actors and old positions from olA olAA = vw.updateOLAs(olA,olAA,disallowL,say) # Next step: # Check of similar positions in olAA and return the indizes of the similar pairs # in the list equalL equalL = vw.selfLs(olAA,say) if say == 1: print('Indizes of equal elements\n') vw.printMX(equalL) else: pass # Again will the actual list olAA with the conflicting actors be replaced # by the actors from olA with the aid of equalL olAA = vw.restoreAAs(equalL, olA, olAA,say) # In the next step: # All actors pointing to new positions which are free (indicated by '_' in the grid) # and which are depending from the directions {2,4,6,8} are only reachable if the two # neighbor cells generated by the directions D-1 and D+1 are free too. Therefore # one has to check whether this is the case. # As previously a disallowL list will be generated and then a reduceAO() and updateOLA() # will be applied. disallowL = vw.checkCornerYX(olAA,mx) if say == 1: print('disallowL after corner cell checks') vw.printMX(disallowL) else: pass # With the aid of disallowL will all the actors in olAA be replaced with # the actors and old positions from olA olAA = vw.updateOLAs(olA,olAA,disallowL,say) # Then reload the olAA list so far into olA for further processing in the normal loop olA = cp.deepcopy(olAA) # Now all actors have reached their new position (or kept their old position). # Finally it is assumed that all actors which can will consume food if available in their cell. # energy = (olA, olF) energy = vw.eating(olA, mx, olF) print('EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n') print('Updated energy levels in olF and olA') vw.printMX(olA) vw.printMX(olF) # UPDATING all FOOD objects # Take the list of all food objects olF # Check whether the energy level (objL index 1) is below Maximum. # If YES add some amount (objL Index 2). # If not do nothing olF=vw.foodUpdate(olF,objL) if say == 1: print('Updated food objects:\n') vw.printMX(olF) else: pass # UPDATING all ACTOR objects # Take the list of all actor objects olA # REDUCE the energy level according to the standard # CHECK whether the energy level is below 0. # If YES add REMOVE AVATAR from grid. olA=vw.actorUpdates(olA,objL,mx,say) if say == 1: print('Updated actor objects:\n') vw.printMX(olA) else: pass # Show summary of all changes in a new 2D-grid WCLCK+=1 # Main reference point for time # Clarify how to continue (MAIN LOOP!) loop=input("\n MAIN LOOP: STOP = 'N', CONTINUE != 'N' \n")