Advertisement
Guest User

Untitled

a guest
Jun 3rd, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.77 KB | None | 0 0
  1. ########
  2. # Python MUD v0.06 by The13Ghost(at)hotmail.com
  3. ########
  4. # some classes for the game... still thinking this out
  5. #
  6. #   -World Classes-
  7. #
  8. #   Objects(Obj) ->  Containers(Cont)
  9. #
  10. #   Containers(Cont) -> Rooms(Room)
  11. #
  12. #   Containers(Cont) -> Mobs(Mob)
  13. #  
  14. #   Mobs(Mob) -> (NPCs,Monsters,Misc)(NPC)
  15. #   Mobs(Mob) -> Player(Konnection)
  16. #
  17. #
  18. #   RoomFactory - generates a room list
  19. #   RoomFactory.generate(amount) - generates a random room list
  20. #   RoomFactory.load_from_file(filename) - loads a room list from a file
  21. #
  22. #   -Net handling- merges with world classes by having the client connection
  23. #   part of the Player
  24. #  
  25. #   Konnection(dispatcher,Mob)
  26. #   NetServer(dispatcher)
  27. #
  28. #   -Game Logic-
  29. #
  30. #   MUDMsg
  31. #   MessageLoop
  32. #   Command
  33. #
  34. ########
  35.  
  36.  
  37. from asyncore import *
  38. from socket import *
  39.  
  40. import string
  41.  
  42. # Constants and stuff
  43. PLAYER_STATE_LOGIN = 0
  44. PLAYER_STATE_USERNAME = 1
  45. PLAYER_STATE_PASSWORD = 2
  46. PLAYER_STATE_INGAME = 3
  47. PLAYER_STATE_FIGHTING = 4
  48. PLAYER_STATE_SHOPPING = 5
  49. PLAYER_STATE_DEAD = 6
  50.  
  51. AI_STATE_IDLE = 0
  52. AI_STATE_MOVING = 1
  53. AI_STATE_FIGHTING = 2
  54.  
  55. # GlobalEvent Queue
  56. globalQueue = []
  57.  
  58. # rooms list?
  59. rooms = []
  60. npc_definitions = []
  61. npc_list = []
  62.  
  63. class Obj:
  64.    
  65.     """ Root Class of all game objects """
  66.    
  67.     _name = ''
  68.     _location = 0
  69.     _description = ''
  70.    
  71.     def __init__(self):
  72.         self._name = ''
  73.         self._location = 0
  74.    
  75.     def __init__(self, name, location):
  76.         self._name = name
  77.         self._location = location
  78.        
  79.     def move(self, to):
  80.         if self._location != 0:
  81.             rooms[self._location].remove(self)
  82.        
  83.         self._location = to
  84.         rooms[self._location].insert(self)
  85.    
  86.     def set_name(self, _string):
  87.         self._name = _string
  88.    
  89.     def get_name(self):
  90.         return self._name
  91.    
  92.     def set_description(self, data):
  93.         self._description = data
  94.    
  95.     def get_description(self):
  96.         return self._description
  97.    
  98.     def set_location(self, id):
  99.         self._location = id
  100.    
  101.     def get_location(self):
  102.         return self._location
  103.        
  104. class Cont (Obj):
  105.  
  106.     """ A container, all Mobs are containers and rooms as well """
  107.    
  108.     _inventory = None
  109.    
  110.     def __init__(self):
  111.         Obj.__init__(self)
  112.         self._inventory = []
  113.        
  114.     def __init__(self, name, location):
  115.         Obj.__init__(self, name, location)
  116.         self._inventory = []
  117.        
  118.     def contents(self):
  119.         pass
  120.    
  121.     def push(self, data):
  122.         pass
  123.        
  124.     def pop(self):
  125.         pass
  126.    
  127.     def insert(self, data):
  128.         self._inventory.append(data)
  129.    
  130.     def remove(self, data):
  131.         self._inventory.remove(data)
  132.    
  133.     def move(self, to):
  134.         Obj.move(self, to)
  135.        
  136. class Room (Cont):
  137.  
  138.     """A Room is just a fancy container"""
  139.    
  140.     _exits = None
  141.     _hidden = None
  142.    
  143.     def __init__(self):
  144.         self._name = "void"
  145.         self._description = "You are in nothingness\r\n"
  146.         self._exits = {}
  147.         self._hidden = {}
  148.         Cont.__init__(self, self._name, 0)
  149.    
  150.     def insert(self, data):
  151.         pass
  152.     def remove(self, data):
  153.         pass
  154.        
  155.     def get_mobs_amount(self):
  156.         count = 0
  157.         for x in self._inventory:
  158.             if isinstance(x, Mob):
  159.                 count += 1
  160.         return count
  161.    
  162.     def get_mobs(self):
  163.         out = []
  164.         for x in self._inventory:
  165.             if isinstance(x, Mob):
  166.                 out.append(x)
  167.         return out
  168.                
  169.     # hidden Exits
  170.     def update_hidden(self, **new):
  171.         self._hidden.update(new)
  172.    
  173.     def get_hidden_exits_as_string(self):
  174.         lineToWrite = "\r\nHidden Exits:\r\n"
  175.         for dir in self._hidden:
  176.             lineToWrite += dir + ', '
  177.         return lineToWrite[:-2] + '\r\n'
  178.    
  179.     def get_hidden_exits(self):
  180.         return self._hidden
  181.    
  182.     # normal Exits
  183.     def update_exits(self, **new):
  184.         self._exits.update(new)
  185.        
  186.     def get_exits(self):
  187.         return self._exits
  188.        
  189.     def get_exits_as_string(self):
  190.         lineToWrite = "\r\nObvious Exits:\r\n"
  191.         for dir in self._exits:
  192.             lineToWrite += dir + ', '
  193.         return lineToWrite[:-2] + '\r\n'
  194.    
  195. class RoomFactory:
  196.    
  197.     """ Generate a Random World or Load one from a file """
  198.    
  199.     def generate(self, amount):
  200.         for x in range(amount):
  201.             rooms.append(Room())
  202.            
  203.     def load_from_file(self, filename):
  204.         # create room 0
  205.         rooms.append(Room())
  206.        
  207.         # open the file and read
  208.         goto_next = 0
  209.         currentLine = ''
  210.         r = rooms[0]
  211.         f = open(filename)
  212.         for line in f:
  213.             line = line.strip()
  214.                
  215.             if len(line) > 0:
  216.                 if goto_next > 0:
  217.                     if line[len(line)-1] == '\\' and line[len(line)-2] != '\\':
  218.                         currentLine += '\r\n' + line[:len(line)-1]
  219.                     else:
  220.                         r.set_description(currentLine + '\r\n' + line + '\r\n')
  221.                         goto_next = 0
  222.                        
  223.                 elif line[0] == '#':
  224.                     continue
  225.                 elif line[0] == 'R' and len(line) > 3:
  226.                     room = int(line[1])
  227.                     rooms.append(Room())
  228.                     r = rooms[room]
  229.                     property = line[2]
  230.                    
  231.                     if property == 'N':
  232.                         if len(line) > 4:
  233.                             line2 = line[4:].strip()
  234.                             newLine = self._return_without_comments(line2)
  235.                             r.set_name(newLine+'\r\n')
  236.                                    
  237.                     elif property == 'D':
  238.                         if len(line) > 4:
  239.                             line2 = line[4:].strip()
  240.                            
  241.                             if line2[len(line2)-1] == '\\' and line2[len(line2)-2] != '\\':
  242.                                     currentLine = line2[:len(line2)-1]
  243.                                     goto_next = 1
  244.                             else:
  245.                                 r.set_description(line2)
  246.                     elif property == 'X':
  247.                         self._parse_exits(r.update_exits, line)
  248.                        
  249.                     elif property == 'H':
  250.                         self._parse_exits(r.update_hidden, line)
  251.                    
  252.                     elif property == 'C':
  253.                         if len(line) > 4:
  254.                             line2 = line[4:].strip()
  255.                             newLine = self._return_without_comments(line2)
  256.                            
  257.                             storing = 0
  258.                             name = ''
  259.                            
  260.                             FOUND = 0
  261.                             for i in range(len(newLine)):
  262.                                 if newLine[i] == '"':
  263.                                     if storing == 1:
  264.                                         storing = 0
  265.                                         for x in npc_definitions:
  266.                                             for y in x.keys():
  267.                                                 if name == y:
  268.                                                     FOUND = 1
  269.                                                     n = NPC()
  270.                                                     n.set_name = name
  271.                                                     n.set_description = x['desc']
  272.                                                     n._Hp = x['HP']
  273.                                                     n._Fatigue = x['Fatigue']
  274.                                                     npc_list.append(n)
  275.                                                     r.append(n)
  276.                                         name = ''
  277.                                     else:
  278.                                         storing = 1
  279.                                 if storing == 1:
  280.                                     name = name + newLine[i]
  281.         f.close()
  282.        
  283.     def _parse_exits(self, room_update, line):
  284.         if len(line) > 4:
  285.             newLine = self._return_without_comments(line)
  286.                            
  287.             for i in range(len(newLine)):
  288.                 if newLine[i] == 'R':
  289.                     if len(newLine[i:]) > 1:
  290.                         which = room_update
  291.                         direction = newLine[i-1]
  292.                         room = newLine[i+1]
  293.                         self._set_exits(which, direction, room)
  294.                        
  295.     def _set_exits(self, room_update, direction, room):
  296.         if direction == 'N':
  297.             #room_update({'North':room})
  298.             room_update(North=room)
  299.                                
  300.         elif direction == 'S':
  301.             #room_update({'South':room})
  302.             room_update(South=room)
  303.            
  304.         elif direction == 'W':
  305.             #room_update({'West':room})
  306.             room_update(West=room)
  307.            
  308.         elif direction == 'E':
  309.             #room_update({'East':room})
  310.             room_update(East=room)
  311.            
  312.         elif direction == 'U':
  313.             #room_update({'Up':room})
  314.             room_update(Up=room)
  315.            
  316.         elif direction == 'D':
  317.             #room_update({'Down':room})
  318.             room_update(Down=room)
  319.            
  320.     def _return_without_comments(self, line):
  321.         comment_pos = line.find('#')
  322.        
  323.         if comment_pos == -1:
  324.             return line
  325.         elif comment_pos == 0:
  326.             return ''
  327.            
  328.         done = 0
  329.         while done < 1:
  330.             if line[(comment_pos-1)] == '\\':
  331.                 comment_pos = line[(comment_pos+1):].find('#')
  332.                 if comment_pos == -1:
  333.                     return line
  334.             else:
  335.                 return line[:comment_pos]
  336.  
  337. class Mob (Cont):
  338.  
  339.     """ any creature or person or NPC etc """
  340.  
  341.     _HP = 0
  342.     _Fatigue = 0
  343.    
  344.     _Endurance = 0
  345.     _Lore = 0
  346.     _Discipline = 0
  347.    
  348. # Stats-attributes?
  349. #   Hp is the same as in most cases
  350. #   fatigue on the other hand serves another aspect,
  351. #   fatigue serves as the limit for your actions, both magic and physical
  352. #   call up magic? fatigue takes a punch if you call too much power
  353. #   or too often
  354. #   swinging a sword? same application
  355. #
  356. # skills-feats?
  357. # spells? i dunno what i should add >.<
  358.  
  359.     def __init__(self, name, location):
  360.         Cont.__init__(self, name, location)
  361.    
  362.     def move(self, to):
  363.         Cont.move(self, to)
  364.        
  365. class NPC (Mob):
  366.  
  367.     """should hold all the AI info needed for the system to control the mob"""
  368. # ID
  369. # Personality:
  370. #   Agressive 0
  371. #   defensive 1
  372. #   Passive   2
  373. # movement:
  374. #   static  0
  375. #   wanders 1
  376. # quest related y/n
  377. # shop y/n
  378. # respawns y/n
  379. # unique y/n
  380.  
  381.     def __init__(self, name, location):
  382.         Mob.__init__(self, name, location)
  383.        
  384. class NPCLoader:
  385.     def __init__(self):
  386.         pass
  387.    
  388.     def load_from_file(self, filename):
  389.         # create room 0
  390.         counter = 0
  391.         npc_definitions.append({})
  392.         definition = npc_definitions[counter]
  393.        
  394.         # open the file and read
  395.         goto_next = 0
  396.         currentLine = ''
  397.         f = open(filename)
  398.         for line in f:
  399.             line = line.strip()
  400.                
  401.             if len(line) > 0:
  402.                 if goto_next > 0:
  403.                     if line[len(line)-1] == '\\' and line[len(line)-2] != '\\':
  404.                         currentLine += '\r\n' + line[:len(line)-1]
  405.                     else:
  406.                         definition.update({'desc':currentLine + '\r\n' + line + '\r\n'})
  407.                         goto_next = 0
  408.                        
  409.                 elif line[0] == '#':
  410.                     continue
  411.                 elif line[0] == 'N' and len(line) > 3:
  412.                     which = int(line[1])
  413.                     if which == counter:
  414.                         npc_definitions.append({})
  415.                         definition = npc_definitions[counter]
  416.                     property = line[2]
  417.                    
  418.                     if property == 'N':
  419.                         if len(line) > 4:
  420.                             line2 = line[4:].strip()
  421.                             newLine = self._return_without_comments(line2)
  422.                             definition.update({'name':newLine})
  423.                                    
  424.                     elif property == 'D':
  425.                         if len(line) > 4:
  426.                             line2 = line[4:].strip()
  427.                            
  428.                             if line2[len(line2)-1] == '\\' and line2[len(line2)-2] != '\\':
  429.                                     currentLine = line2[:len(line2)-1]
  430.                                     goto_next = 1
  431.                             else:
  432.                                 definition.update({'desc':line2})
  433.                     elif property == 'A':
  434.                         self._parse_for_attribs(line, definition.update)
  435.                        
  436.                     #elif property == 'H':
  437.                     #   self._parse_exits(r.update_hidden, line)
  438.                        
  439.         f.close()
  440.        
  441.     def _parse_for_attribs(self,line,update):
  442.         if len(line) > 4:
  443.             newLine = self._return_without_comments(line)
  444.            
  445.             attrib = ''
  446.             num = ''
  447.             lookfor= 0
  448.             for i in range(len(newLine)):
  449.                 if line[i] == ' ' or line[i] == '\t':
  450.                     continue
  451.                 if lookfor == 0:
  452.                     if line[i] in string.letters:
  453.                         attrib = attrib + line[i]
  454.                     else:
  455.                         lookfor = 1
  456.                 if lookfor == 1:
  457.                     if line[i] in string.letters:
  458.                         num = num + line[i]
  459.                     else:
  460.                         lookfor = 0
  461.                         if attrib == 'HP':
  462.                             update({'HP':int(num)})
  463.                         elif attrib == 'FA':
  464.                             update({'Fatigue':int(num)})
  465.                         attrib = ''
  466.                         num = ''
  467.                         if line[i] in string.letters:
  468.                             attrib = attrib + line[i]
  469. class MUDMsg:
  470.  
  471.     """Basic class for a MUDMsg"""
  472.    
  473.     _caller = None
  474.     _contents = None
  475.    
  476.     def __init__(self, data, caller):
  477.         self._caller = caller
  478.         self._contents = data
  479.  
  480.     def get_caller(self):
  481.         return self._caller
  482.    
  483.     def set_caller(self, obj):
  484.         self._caller = obj
  485.    
  486.     def get_content(self):
  487.         return self._contents
  488.    
  489.     def set_content(self, data):
  490.         self._contents = data
  491.    
  492. class MessageLoop:
  493.  
  494.     """Should be named EventHandler... not sure
  495.        Reads the globalQueue and processes events on it"""
  496.        
  497.     def handle_messages(self):
  498.         for event in globalQueue:
  499.             caller = event.get_caller()
  500.             callerState = caller.get_state()
  501.            
  502.             if isinstance(caller, Konnection):
  503.                 if callerState == PLAYER_STATE_LOGIN:
  504.                     if event.get_content() == "LOGGING IN":
  505.                         self.greet(caller)
  506.                         caller.write("\r\nUser Name: ")
  507.                         caller.set_state(PLAYER_STATE_USERNAME)
  508.                        
  509.                 elif callerState == PLAYER_STATE_USERNAME:
  510.                     if len(event.get_content()) > 0:
  511.                         caller.assign_player(event.get_content(), 0)
  512.                         caller.set_state(PLAYER_STATE_PASSWORD)
  513.                         globalQueue.append(MUDMsg("ENTERING PASSWORD SCREEN", caller))
  514.                        
  515.                 elif callerState == PLAYER_STATE_PASSWORD:
  516.                     if event.get_content() == "ENTERING PASSWORD SCREEN":
  517.                         passmasg = "\r\nHi!, " + caller.get_name() + ". Use the Look command. Since this is just for testing" + "\r\nYou will be signed in without an account\r\n"
  518.                         caller.write(passmasg)
  519.                         caller.set_state(PLAYER_STATE_INGAME)
  520.                         caller.move(1)
  521.                    
  522.                 elif callerState == PLAYER_STATE_INGAME:
  523.                     Command(caller, event.get_content())
  524.                     self.prompt(caller)
  525.                    
  526.                 #elif callerState:
  527.                     #pass
  528.                    
  529.             elif isinstance(event.get_caller(), NPC):
  530.                 pass
  531.            
  532.             globalQueue.remove(event)
  533.            
  534.     def prompt(self, caller):
  535.         pass
  536.        
  537.     def greet(self, caller):
  538.         greetmsg = """
  539.         Hello, and welcome to the test Server im working
  540.         on for my newest project!\r\n"""
  541.         caller.write(greetmsg)
  542.                
  543. class Command:
  544.    
  545.     """Parses and handles commands"""
  546.    
  547.     def __init__(self, caller, data):
  548.         if data.lower() == "look":
  549.             self.look(caller)
  550.         elif data == 'exit':
  551.             self.exit(caller)
  552.         elif data.lower() == 'n' or data.lower() == 'north':
  553.             self.move(caller, 'North')
  554.         elif data.lower() == 's' or data.lower() == 'south':
  555.             self.move(caller, 'South')
  556.         elif data.lower() == 'w' or data.lower() == 'west':
  557.             self.move(caller, 'West')
  558.         elif data.lower() == 'e' or data.lower() == 'east':
  559.             self.move(caller, 'East')
  560.         elif data.lower() == 'u' or data.lower() == 'up':
  561.             self.move(caller, 'Up')
  562.         elif data.lower() == 'd' or data.lower() == 'down':
  563.             self.move(caller, 'Down')
  564.    
  565.     def look(self,caller):
  566.         location = caller.get_location()
  567.         caller.write(rooms[location].get_name())
  568.         caller.write(rooms[location].get_description())
  569.         if rooms[location].get_mobs_amount() > 1:
  570.             out = 'You see '
  571.             for x in rooms[location].get_mobs():
  572.                 if not x.get_name() == caller.get_name():
  573.                     out = out + x.get_name() + ', '
  574.             out = out[:-2] + ' in here as well.\r\n'
  575.             caller.write(out)
  576.         caller.write(rooms[location].get_exits_as_string())
  577.    
  578.     def exit(self,caller):
  579.         caller.write("\r\nDisconectting from server...\r\n")
  580.         caller.end_connection()
  581.        
  582.     def move(self, caller, dir):
  583.         location = caller.get_location()
  584.         if dir in rooms[location].get_exits():
  585.             caller.move(int(rooms[location].get_exits()[dir]))
  586.         elif dir in rooms[location].get_hidden_exits():
  587.             caller.move(int(rooms[location].get_hidden_exits()[dir]))
  588.         else:
  589.             caller.write("Can't move there\r\n")
  590.            
  591. class Konnection (dispatcher, Mob):
  592.    
  593.     """Client Connections"""
  594.    
  595.     def __init__(self, address, sk, server):
  596.         self.realSelf = self
  597.         dispatcher.__init__(self, sk)
  598.         self.conn = sk
  599.         self.ip = address[0]
  600.         self.server = server
  601.         self.buffer = []
  602.         self.playState = PLAYER_STATE_LOGIN
  603.         self.write("\r\nConnecting to the Server...\r\n")
  604.         print "Login from " + self.ip
  605.         globalQueue.append(MUDMsg("LOGGING IN",self))
  606.    
  607.     def writable(self):
  608.         return self.buffer
  609.        
  610.     def end_connection(self):
  611.         self.buffer.append(None)
  612.    
  613.     def write(self, data):
  614.         self.buffer.append(data)
  615.    
  616.     def handle_read(self):
  617.         data = self.recv(1024)
  618.  
  619.         if  data != "\n" and  data != "\r\n":
  620.             data = data.strip()
  621.        
  622.         if data:
  623.             globalQueue.append(MUDMsg(data, self))
  624.    
  625.     def handle_write(self):
  626.         if self.buffer[0] is None:
  627.             self.close()
  628.             return
  629.        
  630.         sent = self.send(self.buffer[0])
  631.         if sent >= len(self.buffer[0]):
  632.             self.buffer.pop(0)
  633.         else:
  634.             self.buffer[0] = self.buffer[0][send:]
  635.    
  636.     def handle_close(self):
  637.         print "Disconnection from " + self.ip
  638.         self.server.connections.insert(0, self)
  639.         for x in reversed(self.server.connections):
  640.             if x == self.server.connections[0]:
  641.                 self.server.connections.remove(x)
  642.                
  643.     def get_state(self):
  644.         return self.playState
  645.    
  646.     def set_state(self,STATE):
  647.         self.playState = STATE
  648.    
  649.     def assign_player(self, name, location):
  650.         self._name = name
  651.         self._location = location
  652.        
  653.     def move(self, to):
  654.         Mob.move(self, to)
  655.         globalQueue.append(MUDMsg("look",self))
  656.        
  657. class NetServer (dispatcher):
  658.    
  659.     """ Server class, listens for incoming connections and passes them off to
  660.         a new Konnection """   
  661.  
  662.     def __init__(self, host, port):
  663.         dispatcher.__init__(self)
  664.         self.create_socket(AF_INET, SOCK_STREAM)
  665.         self.set_reuse_addr()
  666.         self.bind((host,port))
  667.         self.listen(5)
  668.         self.connections = []
  669.         print 'Listening on port ' +  `port` + '.'
  670.  
  671.     def writable(self):
  672.         return 0
  673.        
  674.     def handle_accept(self):
  675.         conn, addr= self.accept()
  676.         self.connections.append(Konnection(addr, conn, self))
  677.        
  678.     def end_server(self):
  679.             self.close()
  680.             for co in self.connections:
  681.                 co.write("\r\nSERVER IS SHUTTING DOWN\r\n")
  682.                 co.end_connection()
  683.        
  684. def updateAI():
  685.     pass
  686.    
  687. # Main
  688.  
  689. server = NetServer("0.0.0.0",2002)
  690. game = MessageLoop()
  691. rF = RoomFactory()
  692.  
  693. rF.load_from_file("roomList")
  694.  
  695. try:
  696.     while 1:
  697.         game.handle_messages()
  698.         updateAI()
  699.         poll() #loop(1.0, count = 1)
  700. except KeyboardInterrupt:
  701.     server.end_server()
  702.     loop(1.0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement