Advertisement
Guest User

Bash bot for The Great Escape codingame.com competition

a guest
Feb 22nd, 2015
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 8.65 KB | None | 0 0
  1. # Auto-generated code below aims at helping you parse
  2. # the standard input according to the problem statement.
  3.  
  4. push_queue () {
  5.     local element=$1;
  6.     queue=(${queue[@]} $element);
  7.     elems_queue=$((elems_queue+1));
  8.     #echo "queue after push: "${queue[*]} >&2;
  9. }
  10.  
  11. pop_queue () {
  12.     ret=${queue[$read_iter]};
  13.     read_iter=$((read_iter+1));
  14.     #queue=(${queue[@]:1});
  15.     #echo "queue after pop: "${queue[*]} >&2;
  16. }
  17.  
  18. process_next () {
  19.     local xnext=$1;
  20.     local ynext=$2;
  21.     local dir=$3;
  22.     local dist=$4;
  23.     if [ ${vis[$xnext,$ynext]} == "0" ]; then
  24.         vis[$xnext,$ynext]=$dist;
  25.         fb[$xnext,$ynext]=$((($dir+2)%4));
  26.         element=$xnext$ynext;
  27.         #echo "pushing "$element" at "$dist >&2;
  28.         push_queue $element;
  29.     fi
  30. }
  31.  
  32. can_pass () {
  33.     local curx=$1;
  34.     local cury=$2;
  35.     local dx=${DIRX[$3]};
  36.     local dy=${DIRY[$3]};
  37.     #echo "pass test: "$curx" "$cury" "$dx" "$dy >&2;
  38.     if [ $dx == -1 ]; then
  39.         if [ $curx == 0 ] || [ ${wV[$curx,$cury]} == 1 ]; then
  40.             return 1;
  41.         fi
  42.     elif [ $dx == 1 ]; then
  43.         if [ $curx == 8 ] || [ ${wV[$((curx+1)),$cury]} == 1 ]; then
  44.             return 1;
  45.         fi
  46.     elif [ $dy == -1 ]; then
  47.         if [ $cury == 0 ] || [ ${wH[$curx,$cury]} == 1 ]; then
  48.             return 1;
  49.         fi
  50.     else
  51.         if [ $cury == 8 ] || [ ${wH[$curx,$(($cury+1))]} == 1 ]; then
  52.             return 1;
  53.         fi
  54.     fi
  55.     return 0;
  56. }
  57.  
  58. declare -A vis;
  59. declare -A fb;
  60.  
  61. bfs_goal_reached() {
  62.     local x=$1;
  63.     local y=$2;
  64.     if [ $goal == 1 ] && [ $x == 0 ]; then
  65.         return 0;
  66.     elif [ $goal == 2 ] && [ $y == 8 ]; then
  67.         return 0;
  68.     elif [ $goal == 3 ] && [ $x == 8 ]; then
  69.         return 0;
  70.     fi
  71.     return 1;
  72. }
  73.  
  74.  
  75. #do bfs from the player location filling a distance and a path matrix
  76. #my bash skills are awesome so this can be used at most 2 or 3 times per turn
  77. #before timing out, so no chance to explore the game tree in any depth :)
  78. bfs () {
  79.     local x=$1;
  80.     local y=$2;
  81.  
  82.     for (( i=0; i<9; i++ )) do
  83.         for (( j=0; j<9; j++ )) do
  84.             vis[$i,$j]=0;
  85.             fb[$i,$j]=0;
  86.         done
  87.     done
  88.  
  89.     queue=($x$y);
  90.     read_iter=0;
  91.     elems_queue=1;
  92.     while [ $elems_queue != $read_iter ]
  93.     do
  94.         pop_queue;
  95.         #echo $ret >&2;
  96.         xbfs=${ret:0:1};
  97.         ybfs=${ret:1:1};
  98.         dist=${vis[$xbfs,$ybfs]};
  99.         dist=$((dist+1));
  100.         for (( i=0; i<4; i++ )) do
  101.             if can_pass $xbfs $ybfs $i; then
  102.                 xnext=$((xbfs+${DIRX[$i]}));
  103.                 ynext=$((ybfs+${DIRY[$i]}));
  104.                 if [ $xnext != $x ] || [ $ynext != $y ]; then
  105.                     process_next $xnext $ynext $i $dist;
  106.                     if bfs_goal_reached $xnext $ynext; then
  107.                         return 0;
  108.                     fi
  109.                 fi
  110.             fi
  111.         done
  112.     done
  113.     return 1;
  114. }
  115.  
  116. #backtrack on the path matrix to find the optimal direction from the bot's current location
  117. get_optimal_dir_post_bfs () {
  118.     local x=$xnext;
  119.     local y=$ynext;
  120.     while [ ${vis[$x,$y]} != 0 ]
  121.     do
  122.         dir=${fb[$x,$y]};
  123.         x=$(($x+${DIRX[$dir]}));
  124.         y=$(($y+${DIRY[$dir]}));
  125.     done
  126.     optimal_dir=$((($dir+2)%4));
  127. }
  128.  
  129. #if the player is at x and 1 move from scoring, 1 means block x and x+1 0 means block x-1 and x
  130. #these values are selected to ensure the opponent has to do the largest number of moves assuming
  131. #he/she is following a shortest path and there are no other blocking walls
  132. strat1=(1 0 1 0 1 1 0 1 0)
  133. strat2=(1 0 0 1 0 0 1 1 0)
  134.  
  135. place_v () {
  136.     local x=$1;
  137.     local y=$2;
  138.     local next=$3;
  139.     local ox=$x;
  140.     if [ $ox == 1 ]; then
  141.         ox=0;
  142.     fi
  143.     if [ $next == 1 ]; then
  144.         if [ ${wV[$x,$((y+1))]} == 0 ] && [ ${wH[$ox,$((y+1))]} == 0 ]; then
  145.             echo $x" "$y" V eat bricks :)";
  146.             return 0;
  147.         fi
  148.     else
  149.         if [ ${wV[$x,$((y-1))]} == 0 ] && [ ${wH[$ox,$y]} == 0 ]; then
  150.             echo $x" "$(($y-1))" V eat bricks :)";
  151.             return 0;
  152.         fi
  153.     fi
  154.     return 1;
  155. }
  156.  
  157.  
  158.  
  159. will_block_0 () {
  160.     if [ ${px[0]} == 7 ]; then
  161.         if [ ${wV[8,${py[0]}]} == 0 ]; then
  162.             v=${py[0]}
  163.             if place_v 8 $v ${strat1[$v]} 8; then
  164.                 return 0;
  165.             elif place_v 8 $v ${strat2[$v]} 8; then
  166.                 return 0;
  167.             fi
  168.         fi
  169.     fi
  170.     return 1;
  171. }
  172.  
  173.  
  174.  
  175. will_block_1 () {
  176.     if [ ${px[1]} == 1 ]; then
  177.         if [ ${wV[1,${py[1]}]} == 0 ]; then
  178.             v=${py[1]}
  179.             if place_v 1 $v ${strat1[$v]} 0; then
  180.                 return 0;
  181.             elif place_v 1 $v ${strat2[$v]} 0; then
  182.                 return 0;
  183.             fi
  184.         fi
  185.     fi
  186.     return 1;
  187. }
  188.  
  189. place_h () {
  190.     local x=$1;
  191.     local y=$2;
  192.     local next=$3;
  193.     if [ $next == 1 ]; then
  194.         if [ ${wH[$(($x+1)),$y]} == 0 ] && [ ${wV[$(($x+1)),$y]} == 0 ]; then
  195.             echo $x" 8 H eat bricks :)";
  196.             return 0;
  197.         fi
  198.     else
  199.         if [ ${wH[$(($x-1)),$y]} == 0 ] && [ ${wV[$x,$y]} == 0 ]; then
  200.             echo $(($x-1))" 8 H eat bricks :)";
  201.             return 0;
  202.         fi
  203.     fi
  204.     return 1;
  205. }
  206.  
  207. will_block_2 () {
  208.     if [ ${py[2]} == 7 ]; then
  209.         if [ ${wH[${px[2]},8]} == 0 ]; then
  210.             v=${px[2]}
  211.             if place_h $v 8 ${strat1[$v]}; then
  212.                 return 0;
  213.             elif place_h $v 8 ${strat2[$v]}; then
  214.                 return 0;
  215.             fi
  216.         fi
  217.     fi
  218.     return 1;
  219. }
  220.  
  221.  
  222. # w: width of the board
  223. # h: height of the board
  224. # playerCount: number of players (2 or 3)
  225. # myId: id of my player (0 = 1st player, 1 = 2nd player, ...)
  226. read w h playerCount myId
  227. if [ $myId -eq 0 ]; then
  228.     goal=3;
  229. fi
  230. if [ $myId -eq 1 ]; then
  231.     goal=1;
  232. fi
  233. if [ $myId -eq 2 ]; then
  234.     goal=2;
  235. fi
  236.  
  237. DIRS=("UP" "LEFT" "DOWN" "RIGHT")
  238. DIRX=(0 -1 0 1)
  239. DIRY=(-1 0 1 0)
  240. WINS=("See ya suckers :P" "Bye losers ;)" "So long and thanks for all the walls :D")
  241. # game loop
  242. while true; do
  243.     px=(0 0 0)
  244.     py=(0 0 0)
  245.     for (( i=0; i<playerCount; i++ )); do
  246.         # x: x-coordinate of the player
  247.         # y: y-coordinate of the player
  248.         # wallsLeft: number of walls available for the player
  249.         read x y wallsLeft
  250.         px[$i]=$x;
  251.         py[$i]=$y;
  252.         if [ $i -eq $myId ]; then
  253.             tx=$x
  254.             ty=$y
  255.             mwalls=$wallsLeft
  256.         fi
  257.     done
  258.  
  259.     #wall storage
  260.     declare -A wH
  261.     declare -A wV
  262.     for (( i=0; i<9; i++ )) do
  263.         for (( j=0; j<9; j++ )) do
  264.             wH[$i,$j]=0;
  265.             wV[$i,$j]=0;
  266.         done
  267.     done
  268.  
  269.     # wallCount: number of walls on the board
  270.     read wallCount
  271.     for (( i=0; i<wallCount; i++ )); do
  272.         # wallX: x-coordinate of the wall
  273.         # wallY: y-coordinate of the wall
  274.         # wallOrientation: wall orientation ('H' or 'V')
  275.         read wallX wallY wallOrientation
  276.         if [ ${wallOrientation} == "H" ]; then
  277.             wH[$wallX,$wallY]=1;
  278.             wH[$(($wallX+1)),$wallY]=1;
  279.         else
  280.             wV[$wallX,$wallY]=1;
  281.             wV[$wallX,$(($wallY+1))]=1;
  282.         fi
  283.     done
  284.  
  285.     #determine the shortest path to exit
  286.     xstart=$tx;
  287.     ystart=$ty;
  288.     bfs $tx $ty;
  289.     get_optimal_dir_post_bfs;
  290.     d=$optimal_dir;
  291.  
  292.     #if I don't have more walls to place, take shortest path
  293.     if [ $mwalls == 0 ]; then
  294.         echo ${DIRS[$d]}" No blocking for me no more...";
  295.         continue;
  296.     fi
  297.  
  298.     #eif the next move will win the game for me, make it
  299.     if [ $d == $goal ]; then
  300.         x=$RANDOM
  301.         let "x %= 3"
  302.         message=${WINS[$x]};
  303.         if [ ${DIRS[$d]} == "DOWN" ] && [ $ty == 7 ]; then
  304.             echo "DOWN "$message;
  305.             continue;
  306.         elif [ ${DIRS[$d]} == "LEFT" ] && [ $tx == 1 ]; then
  307.             echo "LEFT "$message;
  308.             continue;
  309.         elif [ ${DIRS[$d]} == "RIGHT" ] && [ $tx == 7 ]; then
  310.             echo "RIGHT "$message;
  311.             continue;
  312.         fi
  313.     fi
  314.  
  315.     #try to block players that are almost scoring,
  316.     #attempt to block the next player to move, first
  317.     if [ $myId == 0 ]; then
  318.         if will_block_1; then
  319.             continue;
  320.         elif will_block_2; then
  321.             continue;
  322.         fi
  323.     elif [ $myId == 1 ]; then
  324.         if will_block_2; then
  325.             continue;
  326.         elif will_block_0; then
  327.             continue;
  328.         fi
  329.     else
  330.         if will_block_0; then
  331.             continue;
  332.         elif will_block_1; then
  333.             continue;
  334.         fi
  335.     fi
  336.  
  337.     #if no wall was used, follow shortest path
  338.     echo ${DIRS[$d]} # action: LEFT, RIGHT, UP, DOWN or "putX putY putOrientation" to place a wall
  339. done
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement