Showing posts with label Script. Show all posts
Showing posts with label Script. Show all posts

Friday, June 14, 2013

Map Generation - Finish Him!

I've got some working code for the Map Gen class I've been working on. There are some issues with placing rooms on top of existing stuff, and I'd like to code something to place walls on the outside of the rectangles that make up my rooms and hallways. But at least it's working now, and it's been pretty fun to work on up to this point.

Loaded the mapgen class into a pygame testbed

I know this is a crappy screenshot, but you can see that there are several rooms (the black rectangles) and hall-objects that connect them. Ignore the crappy images I used for the rooms and player objects. I know they suck, but I've been using them as my standard test images for a while now.

Currently the room generator chooses from a number of pre-loaded images and scales the image to fit the random size. I'm thinking I may change it to tile a floor pattern on the room after a size is chosen. This way I don't end up with floors that are clearly the same image, just stretched to fit. Either that, or just use the same floors and have the room generators just draw random carpets or mats or something to draw attention from the stretched image underneath...

I also want to place some generic walls on each room/hall then add random pictures, posters and windows.

For now though, you just import the class, and run genMaps() and it returns a list (or array if you prefer) of these room/hall objects. You can then use the pygame rectangle objects for collisions  and the pygame image (surface) objects to draw them to another surface.

Here's the source for this class file:
Click here to expand Source
import random, pygame

class RoomObj:
  def update(self,anchorpoint):
    self.rect.left = self.xoffset + anchorpoint[0]
    self.rect.top = self.yoffset + anchorpoint[1]
  
class Room(RoomObj):
  def __init__(self, imageset, direction=0, room_rect=None):
    #RoomObj.__init__(self)
    self.direction = random.randint(1,4) #up, down, left, right
    self.size = (random.randint(400,600),random.randint(500,700))
    self.image = pygame.Surface(self.size)
    pygame.transform.scale(random.choice(imageset), self.size, self.image)
    self.rect = self.image.get_rect()
    if direction==0:
      self.rect.top = 0
      self.rect.left = 0
    if direction==1:
      if self.direction == 2:
        self.direction = 1
      self.rect.bottom = room_rect.top
      self.rect.left = room_rect.left-(self.size[0]/2)
    if direction==2:
      if self.direction == 1:
        self.direction = 2
      self.rect.top = room_rect.bottom
      self.rect.left = room_rect.left-(self.size[0]/2)
    if direction==3:
      if self.direction == 4:
        self.direction = 3
      self.rect.top = room_rect.top-(self.size[1]/2)
      self.rect.right = room_rect.left
    if direction==4:
      if self.direction == 3:
        self.direction = 4
      self.rect.top = room_rect.top-(self.size[1]/2)
      self.rect.left = room_rect.right
    self.xoffset = self.rect.left
    self.yoffset = self.rect.top
  
  
class Hall(RoomObj):
  def __init__(self, direction, room_rect, imageset):
    #RoomObj.__init__(self)
    self.size = (80,random.randint(100,300))
    self.image = pygame.Surface(self.size)
    tmpimage = random.choice(imageset)
    if direction==1:
      self.image = pygame.transform.scale(tmpimage, self.size, self.image)
      self.rect = self.image.get_rect()
      self.rect.bottom = room_rect.top
      self.rect.left = random.randint(room_rect.left, room_rect.right-80)
      self.direction=1
    
    if direction==2:
      self.image = pygame.transform.scale(tmpimage, self.size, self.image)
      self.rect = self.image.get_rect()
      self.rect.top = room_rect.bottom
      self.rect.left = random.randint(room_rect.left, room_rect.right-80)
      self.direction=2
    
    if direction==3:
      self.size = (self.size[1],self.size[0])
      self.image = pygame.Surface(self.size)
      self.image = pygame.transform.rotate(tmpimage, 90)
      #print self.size
      #print self.image.get_size()
      self.image = pygame.transform.scale(tmpimage, self.image.get_size(), self.image)
      self.rect = self.image.get_rect()
      self.rect.top = random.randint(room_rect.top, room_rect.bottom-80)
      self.rect.right = room_rect.left
      self.direction=3
    
    if direction==4:
      self.size = (self.size[1],self.size[0])
      self.image = pygame.Surface(self.size)
      self.image = pygame.transform.rotate(tmpimage, 90)
      self.image = pygame.transform.scale(tmpimage, self.image.get_size(), self.image)
      self.rect = self.image.get_rect()
      self.rect.top = random.randint(room_rect.top, room_rect.bottom-80)
      self.rect.left = room_rect.right
      self.direction=4
    
    self.xoffset = self.rect.left
    self.yoffset = self.rect.top
  
def genMap(size,roomimages,hallimages):
  """
  takes 3 perameters: size (string), roomimages (array of pygame images/surfaces),
  and hallimages (also an array of pygame images)
 
  size should be small, medium or large
  the two arrays should use pygame.image.load() objects or pygame.Surface objects
  e.g. [pygame.image.load("file1.png").convert_alpha(), pygame.image.load("file2.jpg)]
 
  returns an array containing room and hall objects.
 
  each room or hall can be moved through the use of an anchor point variable.
  e.g. mapobjects[0].update(anchorpoint) where anchorpoint is the (x, y) offset
  """
  numofrooms=0
  if size=='small':
    numofrooms = random.randint(3,5)
  if size=='medium':
    numofrooms = random.randint(5,8)
  rooms = []
  map = []
  for i in range(numofrooms):
    if i == 0:
      tmproom = Room(roomimages)
      map.append(tmproom)
      tmphall = Hall(tmproom.direction, tmproom.rect, hallimages)
      map.append(tmphall)
    else:
      if i < len(range(numofrooms))-1:
        tmproom = Room(roomimages, tmphall.direction, tmphall.rect)
        map.append(tmproom)
        tmphall=Hall(tmproom.direction, tmproom.rect, hallimages)
        map.append(tmphall)
      else:
        map.append(Room(roomimages, tmphall.direction, tmphall.rect))
  return map

*Edited - 6-21-2013* I decided to go through the class file and make a few minor updates. I added some checking to see if there was an existing object where the new room was going to be placed. I also changed the logic a bit in the loop that created the Rooms/Halls. I also went through and commented it all. (Except the Room subclass; I figured it was close enough to the Hall, I didn't need to comment both)
In any case, here's the cleaned up class file:

Click here to expand the cleaned up Source
import random, pygame

class RoomObj:
  def __init__(self, wallimgset):
    if self.type == 'room':
      #create walls for a room
      pass
    if self.type == 'hall':
      #create walls for a room
      pass
  def update(self,anchorpoint):
    self.rect.left = self.xoffset + anchorpoint[0]
    self.rect.top = self.yoffset + anchorpoint[1]
  
class Room(RoomObj):
  def __init__(self, imageset, direction=0, room_rect=None, wallimgset=[]):
    #main room rectangle
    self.type = 'room'
    self.direction = random.randint(1,4) #up, down, left, right
    self.size = (random.randint(400,600),random.randint(500,700))
    self.image = pygame.Surface(self.size)
    pygame.transform.scale(random.choice(imageset), self.size, self.image)
    self.rect = self.image.get_rect()
    if direction==0:
      self.rect.top = 0
      self.rect.left = 0
    if direction==1:
      if self.direction == 2:
        self.direction = 1
      self.rect.bottom = room_rect.top
      self.rect.left = room_rect.left-(self.size[0]/2)
    if direction==2:
      if self.direction == 1:
        self.direction = 2
      self.rect.top = room_rect.bottom
      self.rect.left = room_rect.left-(self.size[0]/2)
    if direction==3:
      if self.direction == 4:
        self.direction = 3
      self.rect.top = room_rect.top-(self.size[1]/2)
      self.rect.right = room_rect.left
    if direction==4:
      if self.direction == 3:
        self.direction = 4
      self.rect.top = room_rect.top-(self.size[1]/2)
      self.rect.left = room_rect.right
    self.xoffset = self.rect.left
    self.yoffset = self.rect.top
    RoomObj.__init__(self,wallimgset)
   
   
class Hall(RoomObj):
  #initialize our hall object
  def __init__(self, direction, room_rect, imageset, wallimgset=[]):
    self.type = 'hall'
    #size may want to be changed to be relative to screen size
    self.size = (80,random.randint(100,300))
    #will be surface that is drawn to screen
    self.image = pygame.Surface(self.size)
    #will be drawn to self.image surface
    tmpimage = random.choice(imageset)
    #hall will be facing up and down
    if direction==1:
      self.image = pygame.transform.scale(tmpimage, self.size, self.image)
      self.rect = self.image.get_rect()
      self.rect.bottom = room_rect.top
      self.rect.left = random.randint(room_rect.left, room_rect.right-80)
      self.direction=1
    #hall will be up and down 
    if direction==2:
      self.image = pygame.transform.scale(tmpimage, self.size, self.image)
      self.rect = self.image.get_rect()
      self.rect.top = room_rect.bottom
      self.rect.left = random.randint(room_rect.left, room_rect.right-80)
      self.direction=2
    #hall will be left to right
    if direction==3:
      self.size = (self.size[1],self.size[0])
      self.image = pygame.Surface(self.size)
      self.image = pygame.transform.rotate(tmpimage, 90)
      self.image = pygame.transform.scale(tmpimage, self.image.get_size(), self.image)
      self.rect = self.image.get_rect()
      self.rect.top = random.randint(room_rect.top, room_rect.bottom-80)
      self.rect.right = room_rect.left
      self.direction=3
    #hall will be left to right
    if direction==4:
      self.size = (self.size[1],self.size[0])
      self.image = pygame.Surface(self.size)
      self.image = pygame.transform.rotate(tmpimage, 90)
      self.image = pygame.transform.scale(tmpimage, self.image.get_size(), self.image)
      self.rect = self.image.get_rect()
      self.rect.top = random.randint(room_rect.top, room_rect.bottom-80)
      self.rect.left = room_rect.right
      self.direction=4
    #set offset to use with the update function
    self.xoffset = self.rect.left
    self.yoffset = self.rect.top
    #init the parent class to create the walls and draw the floors
    RoomObj.__init__(self, wallimgset)

def checkForExisting(room, maplist):
  for i in maplist:
    if room.rect.contains(i.rect):
      return True
  return False
   
def genMap(size,roomimages,hallimages):
  """
  takes 3 perameters: size (string), roomimages (array of pygame images/surfaces),
  and hallimages (also an array of pygame images)
 
  size should be small, medium or large
  the two arrays should use pygame.image.load() objects or pygame.Surface objects
  e.g. [pygame.image.load("file1.png").convert_alpha(), pygame.image.load("file2.jpg)]
 
  returns an array containing room and hall objects.
 
  each room or hall can be moved through the use of an anchor point variable.
  e.g. mapobjects[0].update(anchorpoint) where anchorpoint is the (x, y) offset
  """
  #num of rooms will be number of nodes to create
  numofrooms=0
  if size=='small':
    numofrooms = random.randint(3,5)
  if size=='medium':
    numofrooms = random.randint(5,8)
  #add a few to account for joining hall nodes
  numofrooms = numofrooms+(numofrooms-1)
  rooms = []
  map = []
  #while map array length is less than total number of desired nodes...
  while len(map) < numofrooms:
    #first create a room and a hall
    if len(map)==0:
      tmproom = Room(roomimages)
      map.append(tmproom)
      tmphall = Hall(tmproom.direction, tmproom.rect, hallimages)
      map.append(tmphall)
    #create all other nodes
    else:
      # if there are at least 2 spots left on the list, create a room, then a hall
      if len(map) < numofrooms-2:
        tmproom = Room(roomimages, tmphall.direction, tmphall.rect)
        #loop several times to ensure the new room isn't put on top of an old one
        #counter is to ensure we don't end up with an endless loop
        counter = 0
        while checkForExisting(tmproom, map):
          tmproom = Room(roomimages, tmphall.direction, tmphall.rect)
          counter+=1
          #we tried 10 times and couldn't place the room, knock off the last
          #hall and room, and try again
          if counter >10:
            map = map[:-2]
        map.append(tmproom)
        tmphall=Hall(tmproom.direction, tmproom.rect, hallimages)
        map.append(tmphall)
      #only one spot left on our list? create a room
      if len(map) == numofrooms-1:
        tmproom = Room(roomimages, tmphall.direction, tmphall.rect)
        counter=0
        while checkForExisting(tmproom, map):
          tmproom = Room(roomimages, tmphall.direction, tmphall.rect)
          counter+=1
          if counter >10:
            map = map[:-2]
        #map.append(Room(roomimages, tmphall.direction, tmphall.rect))
        map.append(tmproom)
  return map

Tuesday, June 11, 2013

Fill Out Web Forms - Python

I've been doing quite a bit lately with games an pygame. I thought I'd take a break and do something useful. Actually, I found some online drawing that I wanted to win, and they allowed you to submit an entry every day over the course of a month. Obviously I didn't want to log in every day, and even if I did have that level of enthusiasm, my memory would fail at some point and I'd miss a few days here or there.

So the only real solution was to script something and set up a cron job to do it for me every morning. Now, I've never done a script to crawl web pages or anything, so I did a bit of digging and found there are actually quite a few options open for python. Since I was more concerned with just getting something together quickly, I went for what looked to be the easiest option: Mechanize.

Mechanize is a library that can search a URL for existing forms and then allows you to edit form contents and follow links or submit forms. Perfect for what I wanted.

Here's an example script:

#! /usr/bin/env python
import os
from mechanize import Browser

fname="submitResults.txt"
f = open(fname, 'w')

br = Browser()
br.set_proxies({"http":"5.5.5.5:3128"})
br.open("http://www.site.com/giveaway/")
br.select_form(nr=1)
br['fvFirst']='firstName'
br['fvLast']='lastName'
f.write('submitted to site\n')
br.submit()
br.close()
f.close()

Nothing special here. I found out the form and field names ahead of time, by loading up the python interpreter and creating the browser object. Then I used Browser.forms to list the available forms. Then I hard coded the form names into the script. If you really wanted to automate it better, you could set up a function or two to handle that step for you. Have it parse for the fields and look for keywords to make sure you fill in the right values.

If you noticed, I have it write a little message to a text file. That was more for me to validate that cron was running every day. If I checked the text file modification date, it would reflect the last time the script ran successfully. If I had thought about it, I would've added some exceptions that would write errors to the log as well.

In any case, this worked out great. I set up the script with it's own directory and set up a cron job to run every morning around 1am. Still waiting on the results for the giveaway, but at least I know I've entered every day possible. And I learned how to use the mechanize library for web scraping and automated form submissions.

-Newt

Wednesday, June 5, 2013

Map Gen Pseudo Code

I know there are a ton of map generators out there already, but I was considering trying my hand at it as well. More as a learning experience though, and not as an attempt to improve on them in any way. Lord knows I'm not that good.

But I was thinking about it and I think I may be able to pull it off. I threw together some pseudo code to help me out with the logistics, and I wanted to see if anyone had any improvements or maybe some comments.

Here's what I've got so far:

class RoomObj:
  init(type): #types can be hallways or rooms
    attributes, size, type, image etc.
    randomize image based on type given
  update:
    pass

class Room(RoomObj):
  create room type=Room

class Hall(RoomObj):
  create hall type=Hall

def genMap():
  numofrooms = random number of rooms from range
  listofrooms = []
  listofmapobj = []
  for i in range(numofrooms):
    listofrooms.append(Room())
  for i in range(len(listofrooms)):
    create room objects with a "hallway" type
    if i is not the last iterate:
      listofmapobj.append(Hall(listofrooms[i], listofrooms[i+1]))
    listofmapobj.append(listofrooms[i])
  return listofmapobj

I still need to figure out exactly what parameters the room and hallway classes need to be given, but the rooms will initially just create random sized rectangular rooms, then choose a random image from a pre-loaded set. The room placement would have to check to ensure there are no collisions with other room rectangles. And finally the hallway objects would base their size and shape on the locations of the two rooms given as a parameter.

There are a lot of other particulars I still need to figure out, but I think it is doable. and it should be an interesting project to work on.

I'll have to post whatever I end up with at the end of this little adventure.

-newt

Tuesday, May 7, 2013

ArcSight Export Parser Script

For those of you not familiar with it, ArcSight is a pretty robust correlation engine. I've been working with it for quite a while now, and I've never really been happy with the case management system they have. When an alert is triggered, it pulls in some information and saves it to a Case. Unfortunately the management of these cases are kind of messy and can easily become unwieldy for large environments. If you have HP Openview, you can have ArcSight export the cases directly to your ticketing system. But what if you use another ticketing system or a custom built ticketing system? Well, then you can export the files to the system and write your own API to parse the export files and send to the ticketing system of your choice.

That's what I've been working on the last few weeks. With an ArcSight ESM appliance, I'm limited to using bash, perl (limited libraries), or python 2.4. Since I'm more familiar with python, I went that route. Although, you could easily write a parser in perl. In fact, ArcSight has an approved perl script that parses these exports and formats them to a customized email, so you can route events that way. Still python was what I went with.

It's still a work in progress, but here's the basic functions:

# simple function to consolidate headers from base events
def getHeaders(allevents):
   x = []
   for i in range(len(allevents)):
     for thing in allevents[i]:
       if x.count(thing[0]) == 0:
         x.insert(i,thing[0])
   x.reverse()
   return x


# creates an HTML table for use in our web-based ticketing system
def createHtml(baseEventList):
   if os.path.exists('tmp_alert/'):
     removeDir('tmp_alert/')
   fname="tmp_alert/tmp.html"
   d = os.path.dirname(fname)
   if not os.path.exists(d):
     os.makedirs(d)
   f = open(fname, 'w')
   f.write('<!DOCTYPE html>\n')
   f.write('<html>\n')
   f.write('<body>\n')
   f.write('<p>Base Security Events</p>\n')
   #grab the list of headers
   x = getHeaders(baseEventList)
   f.write('<br>\n')

   #the baseTable class is a css file on the server
   #change if you have your own custom style sheet
   f.write('<table class=baseTable>\n')
   f.write('<tr>\n')
   #grab and write headers
   for i in x:
     f.write('<th> %s </th>\n' % i)
   f.write('</tr>\n')
   #loop over all events
   for event in baseEventList:
     f.write('<tr>\n')
     offset = 0
     #loop again to create matching value fields in our table
     for item in range(len(event)):
       itemwritten = False
       for header in x:
         if itemwritten:
           pass
         else:
           if header == event[item][0]:
             f.write('<td> %s</td>\n' % event[item][1])
             itemwritten = True
       f.write('</tr>\n')
   f.write('</table>')
   f.close()


# function to grab all base events using a list of ID numbers
def grabBaseEvents(xmlcontents, baseEventIDList, arcObj):
   #takes the dom document object for a single xml and baseEvent ID list
   baseEvent = []
   allEvents = []
   #for each sec event
   for node in xmlcontents.getElementsByTagName('SecurityEvent'):
     attr_list = node.attributes
     #iterate over sec event attributs
     for attr in range(attr_list.length):
       if attr_list.item(attr).name == 'id':
         #look at all the event IDs
         for baseevent in baseEventIDList:
         #when we have a match, iterate over the current
         #sec event child nodes and append them to a base event list
         baseEvent = []
         if baseevent == attr_list.item(attr).value:
           for x in node.childNodes:
             if x.hasChildNodes():
               if x.nodeName == 'destinationProcessName':
                 arcObj.setAttr('TPN',x.firstChild.nodeValue)
               baseEvent.append((x.nodeName,x.firstChild.nodeValue))
         #when we're done with the base event, append that to an
         #element in the allEvents list
         if len(baseEvent) != 0:
           allEvents.append(baseEvent)
   return allEvents


# Object to store and retrieve RuleFire Event values
class arcObject:
   def __init__(self):
     self.AlertName = "deviceCustomString6 not filled in"
     self.AA = "None"
     self.AH = "None"
     self.AU = "None"
     self.TA = "None"
     self.TH = "None"
     self.TU = "None"
     self.rulename = "None"
     self.time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
     self.filename = "None"
     self.targetproc = "None"
   def getAttr(self, attr):
     if attr == 'AA':
       return self.AA
     elif attr == 'AN':
       return self.AlertName
     elif attr == 'AH':
       return self.AH
     elif attr == 'AU':
       return self.AU
     elif attr == 'TA':
       return self.TA
     elif attr == 'TH':
       return self.TH
     elif attr == 'TU':
       return self.TU
     elif attr == 'rulename':
       return self.rulename
     elif attr == 'time':
       return self.time
     elif attr == 'FN':
       return self.filename
     elif attr == 'TPN':
       return self.targetproc
     else:
       pass
   def setAttr(self, attr, value):
     if attr == 'AA':
       self.AA = value
     elif attr == 'AN':
       self.AlertName = value
     elif attr == 'AH':
       self.AH = value
     elif attr == 'AU':
       self.AU = value
     elif attr == 'TA':
       self.TA = value
     elif attr == 'TH':
       self.TH = value
     elif attr == 'TU':
       self.TU = value
     elif attr == 'rulename':
       self.rulename = value
     elif attr == 'time':
       self.time = value
     elif attr == 'FN':
       self.filename = value
     elif attr == 'TPN':
       self.targetproc = value
     else:
       pass

Essentially I will parse the xml file for a correlation event, then parse the event for specific fields that I will store in the arcsight object. I'm thinking I'll use these fields later to fill in json files that I can post to the webserver. But for now I just store them and then grab the base event ID's associated with each event.

You may have noticed the deviceCustomString6 message I apply to the default alertName variable. That is something I have ArcSight set before it exports the rule-fire. I use that field to store the rulename + time + attacker address and a number of other useful things. The reason was that our ticketing system only lets us query on that alertName field. This way we can search for any of those fields (i.e. all rules triggered by a particular host).

Then I take those ID's, create a list of base events, using my grabBaseEvents function. Then I run that through my createHtml function which will create a table with the base events. This HTML file will probably be zipped up and posted to the web server as well.

Here's what the main loop looks like so far. The addNSend function will be what ultimately adds the fields to the json file and POSTs it to the server.

dir = glob.glob('*.xml')
for xmlfile in dir:
  contents = parse(xmlfile)
  #print "parsing " +xmlfile
  #for each Security Event
  for i in contents.getElementsByTagName('SecurityEvent'):
  x = i.attributes
  #if external ID attribute exists, it's a rule fire
    if x.item(1).name != 'externalID':
    arcObj = arcObject()
    arcObj.setAttr('rulename', x.item(2).value)
    baseEventIDs = []
    #map rule fire values to alert web fields
    for node in i.childNodes:
      if node.hasChildNodes():
        if node.nodeName == 'fileName':
          if node.firstChild.nodeValue != x.item(1).value:
            arcObj.setAttr('FN', node.firstChild.nodeValue)
          elif node.nodeName == 'deviceCustomString6':
            arcObj.setAttr('AN',node.firstChild.nodeValue)
          elif node.nodeName == 'sourceAddress':
            arcObj.setAttr('AA', node.firstChild.nodeValue)
          elif node.nodeName == 'sourceHostName':
            arcObj.setAttr('AH', node.firstChild.nodeValue)
          elif node.nodeName == 'sourceUserName':
            arcObj.setAttr('AU', node.firstChild.nodeValue)
          elif node.nodeName == 'destinationAddress':
            arcObj.setAttr('TA', node.firstChild.nodeValue)
          elif node.nodeName == 'destinationHostName':
            arcObj.setAttr('TH', node.firstChild.nodeValue)
          elif node.nodeName == 'destinationUserName':
            arcObj.setAttr('TU', node.firstChild.nodeValue)
          elif node.nodeName == 'destinationProcessName':
            arcObj.setAttr('TPN', node.firstChild.nodeValue)
          elif node.nodeName == 'managerReceiptTime':
            arcObj.setAttr('time', node.firstChild.nodeValue.rstrip('.0'))
          #check for baseEventIDs
          elif node.nodeName == 'baseEventIds':
            for ref in node.getElementsByTagName('ref'):
              attr_list_obj = ref.attributes
              for attr in range(attr_list_obj.length):
                if attr_list_obj.item(attr).name == 'id':
                  baseEventIDs.append(attr_list_obj.item(attr).value)
                  #find base events and create html to store
                  #grabBaseEvents should return a list of key/value pairs for

                  #each event
            listOfBaseEvents = grabBaseEvents(contents, baseEventIDs, arcObj)
            #createHtml creates the tmp_alert directory and the html
            createHtml(listOfBaseEvents)
          else:
            pass
      #addNsend(arcObj)
  addFileToFolder(xmlfile,'/var/tmp/processed')
  os.remove(xmlfile)


All in all, it works pretty well. I still need to make some formatting changes and add some logic to parse deeper into the xml for some relevant fields, but that's not difficult. Just time consuming. For now it's fine with the handful of fields that it parses for. I guess I could also have it pretty up the html file a bit. As it is, the headers are still smashed together field names like sourceAddress, and what-not.

Maybe when I have it complete, I can post it to ArcSight 724. No telling how many other people are in need of an API for a non-supported ticketing system. With a little modification, I bet this script would work for quite a few other systems.

-Newt

Wednesday, March 27, 2013

Simple Game - Python

So last week I was telling you all about Pygame. Well, it was more about a certain book which covers python game development using pygame. Anyway, I thought I might share a bit of code that I've used in designing my latest python game.

The idea for my game was just a simple hack-n-slash zombie killer. Nothing flashy, just a project to help me keep my python skills from going to utter crap. The game isn't quite finished, but I've learned a few things along the way. And if there's any interest, I can post the source for what I have so far. Just let me know.

Anywho, so where do you start with a python game? Well, if you're using pygame libraries, you'll want to import the libraries, initialize pygame and create a surface to begin drawing.

import pygame

pygame.init()

#create the display object named screen
screen = pygame.display.set_mode((800, 600))

Use whatever size screen you want. And if you feel fancy, you could use the os or pygame libraries to pull the display resolution and use that. To do that with python, just use something like:

screen_x = pygame.display.Info().current_w
screen_y = pygame.display.Info().current_h
screen = pygame.display.set_mode((screen_x,screen_y))

Of course, that's a bit wonky since it's still windowed, and the explorer bar one windows, (or the menu bar on linux distros) will be in the way. To get around this you have to set the display to fullscreen. Here's an example:

#give me the biggest 16bit display available
>>> modes = pygame.display.list_modes(16)
>>> if not modes:
...     print '16bit not supported'
... else:
...     print 'Found Resolution:', modes[0]
...     pygame.display.set_mode(modes[0], FULLSCREEN, 16)


I pulled this example from one of the pygame tutorials located here: http://www.pygame.org/docs/tut/DisplayModes.html

Anyway, once you have this much, you can start drawing to the screen. You can draw images (loaded from a file) or just draw some basic shapes using pygame. Let's start by drawing a background. I'm just going to fill it black.

background = pygame.Surface(screen.get_size())
background.fill((0,0,0))

By the way, if you're going to be using certain colors throughout your code, it makes sense to create some variables to store the rgb tuples. Here's a few to get you started:

black = (0,0,0)
white = (255,255,255)
blue = (0,0,255)
red = (255,0,0)
green = (0,255,0)
#then if you were to use them to fill the background it would look like this
background.fill(black)

So now we've got a black background, so what? Most boring game ever. Let's add a rectangle or something.

pygame.draw.rect(background, green, (100, 100, 100, 100))

You can probably figure that out, but I'm using the pygame draw class to draw a rectangle. This function takes several arguments. First it needs a surface to draw the rectangle to, I used background. Then it takes a tuple for the color. And lastly it needs to know where the rectangle is to be drawn, and the dimensions. These are passed as a tuple of four elements, where the first element is the x coordinate and the second element is the y coordinate. The other two are for width and height. 

This is drawing the rectangle (square actually) object to the background surface. Remember though, that the background was drawn to the screen surface object. So how do we display the changes we just made to the background surface? With the blit function. Each surface object has a number of useful functions that come along with it. Blit basically, redraws one surface to another, updating any changed pixels. Here's a quick example:

screen.blit(background, (0,0))

I'm updating the screen surface with the new background image at the coordinates 0, 0. Since the background is the same size, this will place it directly on top of the screen.

If you run this, it will open your game, draw the rectangle and immediately close it. In order to keep the window open, you have to have the drawing done in some sort of loop, or tell python to wait for input or something to that effect. I may go over the different ways to do that later on, but for now let's just create a little game loop to watch for "events" and quit when it sees a specific event.

while True:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      pygame.quit()

You can probably guess as to what this does for the most part. It's looking through pygame events, which are all sorts of keyboard, and mouse input events. pygame.QUIT is basically when the user clicks the window's X to close the window. Without this you'll have to manually kill the process.

So here's what we have so far:
import pygame

#set up color variables
black = (0,0,0)
white = (255,255,255)
blue = (0,0,255)
red = (255,0,0)
green = (0,255,0)


#start pygame 
pygame.init()

#set up a basic surface
screen = pygame.display.set_mode((800, 600))




#create a background using the screen surface size
background = pygame.Surface(screen.get_size())
background.fill(black)
 

#draw a rectangle to the background surface
pygame.draw.rect(background,green,(100,100,100,100))
 

#draw the whole thing to the screen
screen.blit(background, (0,0))
 

#update your display
pygame.display.update()



#loop through events till we get the signal to close the window

while 1:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      pygame.quit()


And there we go. We have a basic window, with a couple surfaces, and a rectangle object that we have drawn onto them. Now you could do this with a single surface object. I just got into the habit of having two recently. The reason for this is kind of convoluted, and it involves a solution for resizing the window to fit multiple android devices. I'll have to do a post on that down the road, but this post is getting pretty lengthy, so I'll just leave off here for now.

Next time, I'll go into a bit about moving your rectangles and animating using images rather than just using a single static green rectangle. 

-Newt

Wednesday, March 20, 2013

Games with Python

Over the last year and some change, I've been trying to teach myself to code. I started with Python for no real reason other than there were a number of tutorial sites out there that seemed to be pretty complete.

After going through the tutorials and Python documentation (several times in some cases) I found myself wondering how to get in some badly needed practice. After all, in order to code something you need to have some sort of use case in mind. I had found a number of forums offering up ideas for projects, but most were either way above my head or so simple I completed them in minutes.

Longer projects seemed to only hold my interest if there were some actual need for the functionality. Like parsing proxy logs or cmdb data at work. For everything else, I had trouble keeping focused till the completion of the code.

One day, by chance, I found this: http://inventwithpython.com/

At the time Albert Sweigart had only written the first book, but it was enough to renew my interest in learning the language. It's written so that even those with no working knowledge of programming can start creating games and learning python. It goes through a few command-line based games, into graphics based games teaching skills that can easily be translated into scripting and app development.

If you are interested in simple game development, or Python, I would definitely recommend reading his book either by download (for free) or purchasing a hardcopy . The second book is also now available and goes into even more detail with several new game types and development concepts.

I know this sounds like some sort of plug, but I am in no way being compensated for this endorsement. I am merely a grateful reader of his work.

-newt

Wednesday, March 13, 2013

Coding Challenge - Python

So I've been a fan of hackthissite.org for a while now. IT Security has been an interest of mine since I was introduced to computers. They've got tons of hacking challenges to test your skills and teach you new ones.

Just recently though, I noticed that they have coding/scripting challenges now as well. They range from beginner to really difficult, but they've got some really neat ones up there. If you're interested, go register (for free, of course) and try them out for yourself.

The first challenge asks you to code something that can take a number of scrambled words, that were chosen from a file that they provide you with, run the input through a script and produce the unscrambled words in a specific format. i.e. (word1, word2, word3,.....)

Sure you could do it manually, but the page expires a few seconds after the scrambled words are given. So you have to get the scrambled words, run them through your script and submit the output in a few seconds.

There are a ton of ways you could handle this, like sending the output to a file, or console, or even have it go straight to the clipboard so you can paste it into the web form quickly. Even write something to parse the page, pull down the words, and post the output automatically...

Below the break, you can see how I did it using python. Kind of a spoiler if you're planning to try this stuff out yourself, just fyi.

Wednesday, March 6, 2013

Assignment - Python

So, one of my java classes had this assignment a while back to write a command-line application to store user input to a text file. Easy, right? Just loop over the 3 questions and save the user responses on a line in a text file.

Having never worked with Java before, I was surprised at the amount of code necessary to do this. Even without validating user input, the code ended up being around 40 lines.

It got me thinking about how I would do the same thing in python. And I was curious to see how few lines it would take to get the exact same functionality. Here's what I came up with:

file = open("output.txt", 'w')
listOfStuff = []
while True:
    productID = raw_input("enter productID: ")
    product = raw_input("enter product: ")
    price = raw_input("enter price: ")
    listOfStuff.append(productID+" "+product+" "+price+ "\n")
    blah = raw_input("Coninue? yes or no: ")
    if blah in ("no", "nope", "negative"):
        break
for i in listOfStuff:
    file.write(i)
file.close()

13 lines does it. Sure I should do some input validation and all that best-practice jazz, but I didn't have to implement any of that for the java project either, and I was just trying to get the same output and functionality.

If anyone wants to see the crappy java version of this that I did, I guess I could post that too, just leave a comment, or shoot me a message. I only leave it out because 1) I'm lazy, and 2) I have my doubts about anyone actually reading this blog.

-newt