Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Artillery Duel Question

  1. Oct 6, 2005 #1
    Hi,
    I recently wrote a text version of the old DOS Artillery Duel or Atari's Cannon Duel game. In this version, you play against the computer and can control the projectile's angle and velocity.

    I'd now like to add one more dimension whereby the height of the cannons randomly changes for each game instantiation. (For example, the human's cannon might be at a 40 foot elevation while the computer's is at 10 feet).

    The main calculation for the projectile is in the shot.awk script below. I've also included the other two routines in this game for anyone interested.


    cannon.ksh - main program written in Korn Shell. Computer and human take turns shooting at one another

    gettarget.awk - a simple awk script to get the target location (in this case the target is your computer enemy)

    shot.awk - this is the routine (immediately below) where the distance is calculated based upon angle and velocity; and returns the cannon shot (to the main routine, cannon.ksh). I originally got the formulas and a basic understanding of the physics from forums like this one. However, I do not understand how to introduce the additional variable of elevation into the equation. I also don't understand many of the advanced notations and symbols used in formulas that do have a height variable. If you could use the word rather than the symbol (as you see coded in shot.awk) it would help me immensly.

    From what I've read, I think I might have to introduce time into the equation. I can see how this would be required if I were plotting a point (on the screen) for graphics; however, I'm not sure it's necessary for this text version where we just print out how close the shot was to the target.

    Thanks if you can help! -MB


    shot.awk
    ---------
    BEGIN {

    # cannon.ksh passes in user-supplied angle and velocity
    angle=ARGV[1]
    ARGV[1]=""
    velocity=ARGV[2]
    ARGV[2]=""

    gravity=(9.8*-1)

    # convert angle to degrees
    angle=(angle*3.14159265)/180

    # original vector for x and y
    vx=velocity*cos(angle)
    vy=velocity*sin(angle)

    # Midflight (velocity=0, no rise, no fall)
    mf=(vy*-1)/gravity

    # apex - used for graphics. Here for reference only
    #apex=(vy*mf)+(0.5*gravity*(mf*mf))

    # Fullflight is total time of flight
    ff=mf*2

    distance=vx*ff

    printf("%3.0f\n",distance)
    }


    cannon.ksh
    -----------
    #! /bin/ksh

    currentshot=0
    keepshooting=1

    # Computer variables
    comp_angle=45
    comp_hi=100.00
    comp_low=1
    currentguess=50.00


    target=`awk -f gettarget.awk`

    # Set level of difficulty
    echo " "
    echo "Select a level of difficulty: "
    echo " "
    echo "(e)asy: Displays both computer and human parameters"
    echo "(m)edium: Displays only human parameters"
    echo "(h)ard: Displays only + or - for human"
    echo "(v)ery hard: Same as hard but does not even show you the distance to enemy"
    echo " "
    read difficulty
    if [ "$difficulty" != "v" ]
    then
    echo " "
    echo "Target distance: $target"
    fi
    echo " "
    echo "Input angle (0-90) and velocity (1-100)"
    echo " "

    while [ $keepshooting -eq 1 ]
    do
    currentshot=`expr $currentshot + 1`

    #
    # Human shot
    #

    echo " "
    read parms

    angle=`echo $parms | awk ' { print $1 } '`
    velocity=`echo $parms | awk ' { print $2 } '`

    distance=`awk -f shot.awk $angle $velocity`

    if [ $distance -eq $target ]
    then
    echo " "
    echo " " # <--- this is Control-G to make the computer BEEP
    echo " "
    echo " "
    echo " "
    banner "BOOM!" # <--- banner is an old Unix utility to display the text in larger banner font
    echo " "
    echo "You hit the target at $distance feet in $currentshot shots! "
    echo "Computer was using $comp_angle $currentguess"
    echo " "
    keepshooting=0
    else

    echo " "

    if [ $distance -gt target ]
    then
    delta=`expr $distance - $target`
    if [ "$difficulty" = "e" ] || [ "$difficulty" = "m" ]
    then
    echo "+${delta}"
    else
    if [ "$difficulty" = "h" ] || [ "$difficulty" = "v" ]
    then
    echo "+ you overshot"
    fi
    fi
    else
    delta=`expr $target - $distance`
    if [ "$difficulty" = "e" ] || [ "$difficulty" = "m" ]
    then
    echo "-${delta}"
    else
    if [ "$difficulty" = "h" ] || [ "$difficulty" = "v" ]
    then
    echo "- you undershot"
    fi
    fi
    fi

    fi

    #
    # Computer shot
    #

    # Only take a shot if the human didn't just hit us
    if [ $keepshooting -eq 1 ]
    then
    distance=`awk -f shot.awk $comp_angle $currentguess`

    if [ $distance -eq $target ]
    then
    echo " "
    echo " "
    echo " "
    echo " "
    echo " "
    banner "BAM!"
    echo " "
    echo "The computer got you at $comp_angle $currentguess in $currentshot shots! Distance: $target"
    echo " "
    keepshooting=0
    else

    echo " "

    if [ $distance -gt target ]
    then
    delta=`expr $distance - $target`
    echo " "

    if [ "$difficulty" = "e" ]
    then
    echo "Computer: $comp_angle $currentguess +${delta}"
    else
    echo "Computer missed!"
    fi

    # low routine from guess
    comp_hi=$currentguess
    # need awk for fractions
    currentguess=`echo $currentguess $comp_low | awk ' { printf("%2.2f",($1+$2)/2 ) } ' `

    else
    delta=`expr $target - $distance`
    echo " "
    if [ "$difficulty" = "e" ]
    then
    echo "Computer: $comp_angle $currentguess -${delta}"
    else
    echo "Computer missed!"
    fi

    # hi routine from guess
    comp_low=$currentguess
    # need awk for fractions
    currentguess=`echo $currentguess $comp_hi | awk ' { printf("%2.2f",($1+$2)/2 ) } ' `

    # Check for 99.99 (in order to guess 100) - must convert to int
    tcurrentguess=`echo $currentguess | awk ' { printf("%d",$1*100) } ' `
    if [ $tcurrentguess -eq 9999 ]
    then
    currentguess=100
    fi
    fi

    fi
    fi

    done

    exit

    gettarget.awk
    -------------
    BEGIN {
    trand=srand()
    target=int(1000*rand())+1
    printf("%d\n",target)
    }
     
  2. jcsd
  3. Nov 10, 2005 #2
    Cannon on a hill, lobbing the shot:
    distance=vx*(vy/gravity+(sqrt((vy*vy)/(gravity*gravity)-2*height/gravity)))

    Steep angle shot:
    <snip> vx=velocity*cos(angle)
    vy=velocity*sin(angle)

    time=tgt_distance/vx

    height=vy*time-.5*gravity*(time*time)

    Steep angle downhill shot:

    vx=velocity*cos(angle)
    vy=velocity*sin(angle)

    # For downhill tight shot, vertical velocity is negative
    vy = vy * -1

    time=tgt_distance/vx

    height=vy*time-.5*gravity*(time*time)
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?