<commit_before>#!/bin/bash

declare -ia board
declare -i pieces=0
declare header="Bash 2048 v0.1 by <NAME> (<EMAIL>)"
declare ESC=$'\e'
declare lastmatch
declare change

function print_header {
  echo $header pieces=$pieces
  echo
}

function print_board {
  clear
  print_header
  printf '/------|------|------|------\\\n'
  for l in $(seq 0 3); do
    printf '| %4d | %4d | %4d | %4d |\n' ${board[l*4]} ${board[l*4+1]} ${board[l*4+2]} ${board[l*4+3]}
    let l==3 || printf '|------|------|------|------|\n'
  done
  printf '\\------|------|------|------/\n'
}

function generate_token {
  let pieces==16 && end_game 0
  while true; do
    let pos=RANDOM%16
    let board[$pos] || {
      let value=RANDOM%10?2:4
      board[$pos]=$value
      break;
    }
  done
  let pieces++
}

function push_fields {
  case $3 in
    "up")
      let "first=$2*4+$1"
      let "second=($2+1)*4+$1"
      ;;
    "down")
      let "first=($2+1)*4+$1"
      let "second=$2*4+$1"
      ;;
    "left")
      let "first=$1*4+$2"
      let "second=$1*4+($2+1)"
      ;;
    "right")
      let "first=$1*4+($2+1)"
      let "second=$1*4+$2"
      ;;
  esac      
  let ${board[$first]} || { 
    let ${board[$second]} && {
      board[$first]=${board[$second]}
      let board[$second]=0
      let change=1
      return
    }
    return
  }
  let "(${board[$first]}==${board[second]})&(lastmatch<$2)" && { 
    let board[$first]*=2
    let "board[$first]==2048" && end_game 1
    let board[$second]=0
    let lastmatch=$2+1
    let pieces-=1
    let change=1
  }
}

function make_push_rec {
  local n
  let "$2==$3" && return 
  let "n=$2+1"
  push_fields $1 $2 $4
  let "n!=$3" && {
    make_push_rec $1 $n $3 $4
    push_fields $1 $2 $4
    push_fields $1 $n $4
  }  
}

function push_tokens {
  let change=0
  let lastmatch=-1
  read -d '' -sn 1
  test "$REPLY" = "$ESC" && {
    read -d '' -sn 1 -t1
    test "$REPLY" = "[" && {
      read -d '' -sn 1 -t1
      case $REPLY in
        A) for i in $(seq 0 3); do lastmatch=-1; make_push_rec $i 0 3 up; done;;
        B) for i in $(seq 0 3); do lastmatch=-1; make_push_rec $i 0 3 down; done;;
        C) for i in $(seq 0 3); do lastmatch=-1; make_push_rec $i 0 3 right; done;;
        D) for i in $(seq 0 3); do lastmatch=-1; make_push_rec $i 0 3 left; done;;
      esac
    }
  }
}

function end_game {
  print_board
  echo GAME OVER
  let $1 && {
    echo "Congratulations you have achieved 2048"
    exit 0
  }
  echo "You have lost, better luck next time."
  exit 0
}

#init board
for i in $(seq 0 15); do board[$i]="0"; done
generate_token
generate_token
while true; do
  print_board
  push_tokens
  let change && generate_token
done <commit_msg>multiple changes to logic and UI, support for boards of different sizes<commit_after>#!/bin/bash

declare -ia board
declare -ia joins
declare -i pieces=0
declare -i board_size=5
declare -i target=2048

header="Bash 2048 v0.2 by <NAME> (<EMAIL>)"
ESC=$'\e'

function print_header {
  echo $header pieces=$pieces
  echo
}

function print_board {
  clear
  print_header
  printf '/------'
  for l in $(seq 1 $index_max); do
    printf '|------'
  done
  printf '\\\n'
  for l in $(seq 0 $index_max); do
    printf '| '
    for m in $(seq 0 $index_max); do
      if let ${board[l*$board_size+m]}; then
        if let '(last_added==(l*board_size+m))|(first_round==(l*board_size+m))'; then
          printf '\033[1m\033[31m%4d \033[0m| ' ${board[l*$board_size+m]}
        else
          printf '%4d | ' ${board[l*$board_size+m]}
        fi
      else
        printf '     | '
      fi
    done
    let l==$index_max || {
      printf '\n|------'
      for l in $(seq 1 $index_max); do
        printf '|------'
      done
      printf '|\n'
    }
  done
  printf '\n\\------'
  for l in $(seq 1 $index_max); do
    printf '|------'
  done
  printf '/\n'
}

function generate_token {
  let pieces==fields_total && end_game 0
  while true; do
    let pos=RANDOM%fields_total
    let board[$pos] || {
      let value=RANDOM%10?2:4
      board[$pos]=$value
      last_added=$pos
      break;
    }
  done
  let pieces++
}

function push_fields {
  case $3 in
    "up")
      let "first=$2*$board_size+$1"
      let "second=($2+1)*$board_size+$1"
      ;;
    "down")
      let "first=($2+1)*$board_size+$1"
      let "second=$2*$board_size+$1"
      ;;
    "left")
      let "first=$1*$board_size+$2"
      let "second=$1*$board_size+($2+1)"
      ;;
    "right")
      let "first=$1*$board_size+($2+1)"
      let "second=$1*$board_size+$2"
      ;;
  esac
  let "can_join=(!joins[$2])&(!joins[$2+1])"
  let ${board[$first]} || { 
    let ${board[$second]} && {
      board[$first]=${board[$second]}
      joins[$first]=${joins[$second]}
      let board[$second]=0
      let change=1
      return
    }
    return
  }
  let "(${board[$first]}==${board[second]})&(can_join)" && { 
    let board[$first]*=2
    let "board[$first]==$target" && end_game 1
    let board[$second]=0
    let joins[$first]=1
    let pieces-=1
    let change=1
  }
}

function make_push_rec {
  local n
  let "$2==$3" && return 
  let "n=$2+1"
  push_fields $1 $2 $4
  let "n!=$3" && {
    make_push_rec $1 $n $3 $4
  }  
}

function push_tokens {
  for i in $(seq 0 $index_max); do
    for j in $(seq 0 $index_max); do joins[$j]="0"; done
    for pass in $(seq $index_max -1 1); do
      make_push_rec $i 0 $pass $1 
    done
  done
}

function key_react {
  let change=0
  read -d '' -sn 1
  test "$REPLY" = "$ESC" && {
    read -d '' -sn 1 -t1
    test "$REPLY" = "[" && {
      read -d '' -sn 1 -t1
      case $REPLY in
        A) push_tokens up;;
        B) push_tokens down;;
        C) push_tokens right;;
        D) push_tokens left;;
      esac
    }
  }
}

function end_game {
  print_board
  echo GAME OVER
  let $1 && {
    echo "Congratulations you have achieved $target"
    exit 0
  }
  echo "You have lost, better luck next time."
  exit 0
}

#init board
let fields_total=board_size*board_size
let index_max=board_size-1
for i in $(seq 0 $fields_total); do board[$i]="0"; done
for i in $(seq 0 $index_max); do joins[$i]="0"; done
generate_token
first_round=$last_added
generate_token
while true; do
  print_board
  key_react
  let change && generate_token
  first_round=-1
done 
{'fraction_non_alphanumeric': 0.1831143864146107, 'fraction_numerical': 0.03668695930791413, 'mean_word_length': 2.3929347826086955, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1586688', 'n_tokens_mistral': 2512, 'n_tokens_neox': 2392, 'n_words': 647}