Tuesday, May 27, 2014

DEFCON 2014 quals - Zombies

This challenge consisted of a scripting game. The player was asked to choose a gun and pistol, and then use them to save 100 puppies from attacking zombies.

To shoot a zombie, the player had to give the weapon used (pistol or rifle), and the angle, distance and height of the shot (zombies and puppies exist on a 2D grid relative to the player. For the first 10 rounds the zombie would be stationary. However, the final 90 rounds had a moving zombie. For this, the player was given the location of the zombie and puppy, and the time it would take for the zombie to get to the puppy. While we initially expected that the player and puppy would begin to move in later rounds, this thankfully never happened.

For the first 10 rounds, we used physics to calculate bullet drop due to gravity, and basic trig to get the angle.

For the remaining 90 rounds, we calculated the ratio of the time at which we would shoot the zombie over time it would have taken that zombie to reach the puppy. This was multiplied by the distance between the two, and added to the zombie's initial location to get the location of the zombie at time of the shot. Additionally, we had to integrate bullet drop in both the height and angle of shot.

Even with this, we would occasionally get unexpected failures (<5%). We compensated for this by starting many connections, and one eventually hit 100%

-albntomat0

Code
from __future__ import division
import socket,math,time
ip = 'zombies_8977dda19ee030d0ea35e97ad2439319.2014.shallweplayaga.me'
port = 20689

def main():
 s = socket.socket()
 s.connect((ip,port))

 print(s.recv(1024))
 print("test")
 s.send("2\n")
 print("[+] Sent gun choice")
 print(s.recv(1024))
 s.send("3\n")
 print("[+] Sent pistol choice")
 for i in range(9):
  res = (s.recv(1024))
  print(res)
  temp = res.split(" ")
  numbers = []
  print("##########################")
  for a in temp:
   if a[:-1].isdigit():
    numbers += [a[:-1]]
    print(a)
  print("###########################")
  dist = numbers[len(numbers)-2]
  height = numbers[len(numbers)-1]
  print("dist is: " + dist)
  print("height is " + height)
  shoot(s,int(height),int(dist))
 while(True):
  res = (s.recv(1024))
  print(res)
  temp = res.split(" ")
  ztime = []
  numbers = []
  for a in temp:
   if a.isdigit(): #ztime value
    ztime += [a]
   elif a[:-1].isdigit(): #distance value
    numbers += [a[:-1]]
  print(ztime)
  print("#####")
  print(numbers)
  zdist = int(numbers[len(numbers)-4])
  zheight = int(numbers[len(numbers)-3])
  pdist = int(numbers[len(numbers)-2])
  pheight = int(numbers[len(numbers)-1])
  currTime = 1
  finTime = int(ztime[0])
  print("pdist is: " + str(pdist))
  print("pheight is " + str(pheight))
  print("zdist is: " + str(zdist))
  print("zheight is " + str(zheight))
  for z in range(2):
   print(s.recv(64))
   currTime += 1
  shoot2(s,zheight,zdist,pheight,pdist,currTime,finTime)
  #print(s.recv(1024))

def shoot2(s,zombieHIn,zombieDIn,puppieHIn,puppieDIn,currTime,finalTime):
 rifle = 975.0
 pist = 375.0
 weapon = "r"
 ztimeRatio = currTime/finalTime
 heightIn = (puppieHIn - zombieHIn) * ztimeRatio + zombieHIn
 distanceIn = (puppieDIn - zombieDIn) * ztimeRatio + zombieDIn
 print("Time " + str(ztimeRatio))
 print("Height Target " + str(heightIn))
 print("Dist Target " + str(distanceIn))
 direct = math.hypot(distanceIn,heightIn)
 if(direct < 50):
  print("[+] using pistol")
  weapon = "p"
  ztime = direct/pist
 else:
  ztime = direct/rifle
 drop = 4.9 * ztime * ztime
 print("here")
 print(ztime)
 print(drop)
 height = heightIn + drop
 distance = distanceIn#before lead
 distance = distance + ((puppieDIn - zombieDIn)/finalTime * ztime)
 
 rad = math.atan2(height,distanceIn)
 angle = math.degrees(rad)

 response = weapon + ", " + str(angle) + " , " + str(distanceIn) + " , " + str(heightIn)
 print("[+] Firing: " + response)
 s.send(response + "\n")

def shoot(s,heightIn,distanceIn):
 rifle = 975.0
 pist = 375.0
 weapon = "r"
 direct = math.hypot(distanceIn,heightIn)
 if(direct < 50):
  print("[+] using pistol")
  weapon = "p"
  ztime = direct/pist
 else:
  ztime = direct/rifle
 drop = 4.9 * ztime * ztime
 print("here")
 print(ztime)
 print(drop)
 height = heightIn + drop
 distance = distanceIn
 rad = math.atan2(height,distance)
 angle = math.degrees(rad)
 response = weapon + "," + str(angle) + "," + str(distance) + "," + str(height+drop)
 print("[+] Firing: " + response)
 s.send(response + "\n")

main()

No comments:

Post a Comment