HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashMinor

Game of Life Kata in Bash

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
lifekatagamebash

Problem

I've implemented a Game of Life Kata with the aim to get to know Consul's K/V store. Although not the main purpose of the exercise, it would be nice if somebody reviewed some of the bash code in the Kata, as my experience with bash is not as extended as I would like. My main concern is about writing idiomatic bash (ie. doing things as readers would expect), although any kind of comment will be appreciated.

The whole project can be found here. Here is the relevant code snippets:

cell.sh

```
#!/usr/bin/env bash

row=$(( $CELL_NUMBER / $GRID_WIDTH ))
column=$(( $CELL_NUMBER % $GRID_WIDTH ))
total_cells=$(( GRID_WIDTH * $GRID_HEIGHT - 1 ))

calculate_neighbour_number() {
relative_x=$1
relative_y=$2
echo $(( (((($CELL_NUMBER + $relative_x - $GRID_WIDTH) % $GRID_WIDTH) + $GRID_WIDTH) % $GRID_WIDTH) + ($GRID_WIDTH * (((($row + $relative_y) % $GRID_HEIGHT) + $GRID_HEIGHT) % $GRID_HEIGHT)) ))
}

update_state() {
state=$1
round=$2
curl -X PUT -d "$state" --output /dev/null -s http://$CONSUL_HOST/v1/kv/round/$round/cells/$(ensure_leading_zeros $CELL_NUMBER)
curl -X PUT -d "$state" --output /dev/null -s http://$CONSUL_HOST/v1/kv/cells/$(ensure_leading_zeros $CELL_NUMBER)
}

ensure_leading_zeros() {
cell_number=$1
echo $(printf "%0*d " $leading_zeros $cell_number)
}

export leading_zeros=${#total_cells}
export -f ensure_leading_zeros

neighbours=(
$(calculate_neighbour_number -1 -1)
$(calculate_neighbour_number 0 -1)
$(calculate_neighbour_number 1 -1)
$(calculate_neighbour_number -1 0)
$(calculate_neighbour_number 1 0)
$(calculate_neighbour_number -1 +1)
$(calculate_neighbour_number 0 +1)
$(calculate_neighbour_number 1 +1)
)

echo "Waiting for game to begin..." # print waiting dots in newline, otherwise docker won't log anything until waiting is done
until curl -s --fail --output /dev/null http://$CONSUL_HOST/v1/kv/round;
do
printf "."
sleep 1
done
echo ": READY"

state=$INITIAL_STATE

update_state $

Solution

The right tool for the job

It's a good aim to use the right tool for the job. Bash is a great tool to glue together high level commands, so that they can be combined flexibly. Bash is awkward and inefficient to implement nontrivial logic. I understand you want to practice Bash, but I suggest to choose more suitable exercise targets.

Math in Bash

You can omit most $ signs of variables within ((...)). It will simplify these expressions a bit. You did omit in a few places. Not omitting everywhere consistently can be confusing.

while vs until

I'm not a fan of until, because until cmd is exactly the same as while ! cmd. Adding a new keyword for something that could be perfectly reasonably accomplished with something that exists seems like a bad idea. I suggest to limit the vocabulary used by your program to the minimum set of necessary terms, and until can be easily cut out.

seq is not portable

You can use a counting loop, or a {start..end} expression instead.

Isolating technical details

Several curl commands are sprinkled throughout the scripts. It would be better to wrap these into higher level functions. Not only that would let your main functions operate using the language of the problem domain, it would also help reducing code duplication.

Context

StackExchange Code Review Q#144299, answer score: 3

Revisions (0)

No revisions yet.