|
|
|
@ -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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|