diff --git a/robocode-svm b/robocode-svm index 75908ab..ed98867 100755 --- a/robocode-svm +++ b/robocode-svm @@ -1,114 +1,115 @@ #!/usr/bin/env bash set -u -# set -x +#set -x # File locations -datadir="data" +dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +datadir="$dir/data" results="$datadir/battle.data" settings="$datadir/settings.last.battle" training="$datadir/training.scale.data" testing="$datadir/testing.scale.data" # Battle parameters -rounds=1000 +rounds=6 width=500 height=500 robot1="sample.Corners" robot2="sample.Fire" -# Delete the battle data so the will get freshly generated -flush_battle_data() { - rm -f "$datadir/*" - touch "$results" -} - -# Help function -show_help() { - echo "USAGE: robocode-svm OPTIONS" - echo " -v, --visualize Shows visual run of the battle" - echo " -x The x coordinate of the second robot, used with -v" - echo " -y The y coordinate of the second robot, used with -v" - echo " -a, --accuracy Only show the accuracy of the SVM prediction" - echo " -c, --clean Clean run (deletes everything inside data folder)" - echo " -h, --help Show this help" -} - -# Run battle without GUI, following the settings file, and returning the lines containing winners -run_battle() { - robocode -nodisplay -battle "$settings" | tail -2; -} - - # Prepare the data directory mkdir -p "$datadir/"; +# Iterate over arguments while :; do - case $1 in - # Regenerate data files - -c|--clean) - flush_battle_data + # If there are any + if [ $# -gt 0 ] ; then + case $1 in + # Regenerate data files + -c|--clean) + rm -rf "$datadir" ;; - # Call a "show_help" function to display a synopsis, then exit. - -h|-\?|--help) - show_help + # Call a "show_help" function to display a synopsis, then exit. + -h|-\?|--help) + echo "Generate the data required for SVM classification." + echo "USAGE: robocode-svm [OPTION] [COORDINATES]" + echo " -v, --visualize Shows visual run of the battle" + echo " -x The x coordinate of the second robot, used with -v" + echo " -y The y coordinate of the second robot, used with -v" + echo " -a, --accuracy Only show the accuracy of the SVM prediction" + echo " -c, --clean Regenerate the battle data (may take a very long time)" + echo " -h, --help Show this help" exit ;; - - # Unrecognized parameter - -?*) + # Just accuracy + #-a|--accuracy) + #show_accuracy + #exit + #;; + # Unrecognized parameter + -?*) printf 'WARNING: Unknown option (ignored): %s\n' "$1" >&2 ;; - # Default case: If no more options then break out of the loop. - *) + # Default case: If no more options then break out of the loop. + *) break esac # "command" reduces the chance of fatal errors in many shells. command shift +else + break +fi done - -# Repeat the battle desired number of times -for i in $(seq 1 $rounds); -do - # Generate input parameters - number=$RANDOM; let "number %= $width"; x=$number - number=$RANDOM; let "number %= $height"; y=$number - number=$RANDOM; let "number %= 360"; alpha=$number - - # Write current settings to a file; first robot starts in the middle, with fixed gun angle; - # the other one start at random known position, with random known gun angle - echo "#Battle Properties -robocode.battleField.width=$width -robocode.battleField.height=$height -robocode.battle.numRounds=1 -robocode.battle.gunCoolingRate=0.07 -robocode.battle.rules.inactivityTime=450 -robocode.battle.selectedRobots=$robot1,$robot2 -robocode.battle.initialPositions=($((width/2)),$((height/2)),0),($x,$y,$alpha)" > "$settings" - - # If the robots are of the same name - if [ "$robot1" == "$robot2" ] ; then - # Their order number is in the bracket after the name - winner=$(run_battle | awk 'NR==1 {print substr($3,2,1)}') - else - # Otherwise we need to match the actual names - winner=$(run_battle | awk 'NR==1F {print $2}') +# Generate the battle data (run 1000 battles) for a SVM classification +# If the data file has required amount if data +lines=$(wc -l < "$results") +if [[ "$lines" -eq "$rounds" ]] ; then + echo "Data are already generated." +else + # Repeat the battle desired number of times (till the battle data file does not contain $rounds entries + echo "Generating the data for SVM predition. Depending on the machine, this may take very long time." + delta=$((rounds - lines)) + for ((i = 1; i <= "$delta"; i++)) ; do + # Generate input parameters + number=$RANDOM; let "number %= $width"; x=$number + number=$RANDOM; let "number %= $height"; y=$number + number=$RANDOM; let "number %= 360"; alpha=$number + + # Write current settings to a file; first robot starts in the middle, with fixed gun angle; + # the other one start at random known position, with random known gun angle + { + echo "#Battle Properties" + echo "robocode.battleField.width=$width" + echo "robocode.battleField.height=$height" + echo "robocode.battle.numRounds=1" + echo "robocode.battle.gunCoolingRate=0.07" + echo "robocode.battle.rules.inactivityTime=450" + echo "robocode.battle.selectedRobots=$robot1,$robot2" + echo "robocode.battle.initialPositions=($((width/2)),$((height/2)),0),($x,$y,$alpha)" + } > "$settings" + + # Run battle without GUI, following the settings file, and returning the lines containing winners + winner=$(robocode -nodisplay -battle "$settings" | tail -2| awk 'NR==1F {print $2}') if [ "$winner" == "$robot1" ] ; then winner=1 else winner=2 fi - fi - # Inform user about the winner of current round and append the results to the file - echo "Round $i winner: $winner" - # echo "$winner 1:$x 2:$y" >> "$results" - echo "$winner 1:$x 2:$y 3:$alpha" >> "$results" -done + # Append the result of the battle to the battle data file + echo "$winner 1:$x 2:$y 3:$alpha" >> "$results" + # Print a dot to infrom user tht something is happening + printf "." + done + printf "\nData generation successful.\n" +fi + +# Calculate and print the acuuracy of classification, given the test sample # Calculate the lines needed to split the data to 90% and 10% tr=$(bc <<< "scale=0; $rounds * 0.9 / 1"); te=$(bc <<< "scale=0; ($rounds - $tr) / 1"); @@ -117,3 +118,4 @@ te=$(bc <<< "scale=0; ($rounds - $tr) / 1"); # misuse tee for 'process substituion' and send its stdout do /dev/null svm-scale -l 0 -u 1 "$results" | tee >(head -n "$tr" > "$training") >(tail -n "$te" > "$testing") > /dev/null +