title: ASCII Scores

text:
# Question
Title: ASCII Scores
Digging around in the depths of your temp folder, you find some compositions for the piano. Unfortunately, these compositions were written with note names and durations only, and you only have access to a text terminal. Therefore, your task is to write a program to display the compositions as ASCII art.

## Input

Your program should accept two strings as input. The first string will represent the notes of the top staff (with the treble clef), while the second string will represent the notes of the bottom staff.

The notes will be passed in scientific pitch notation. The top staff's notes will always be between `C4` and `C6` inclusive. The bottom staff's notes will always be between `C2` and `C4` inclusive.

Each note will come with a duration, which will be one of: `1`, `2`, `4`, `8`. These represent a whole note (semibreve), a half note (minim), a quarter note (crotchet), and an eighth note (quaver) respectively.

Notes of any other duration will never appear in the input.

How the note and duration is separated, and how each note is separated from other notes in the input is up to your discretion. The following is a sample input for the top staff:

```
E4/4 A4/8 C#5/8 E5/2

```

Here, the notes are separated by a space, and the duration is separated from the note with a forward slash. These delimeters are not fixed, and you may choose to change them or omit them altogether.

You may assume there is at least one note in each staff. There are no rests in the input.

## Output

Your program is to output the score as ASCII art, conforming to the following descriptions.

The clefs should be the first thing at the left of your output (the distance between the two staves should not be changed):

```
       ^
      | |
------|/----
      /
-----/|-----
    / |
---/--__----
   | /  \
---\-\|-|---
    \ | /
------|-----
      |
    \_/

----___-----
   /   \ |
---\---|----
       | |
-------/----
      /
-----/------

------------

```

A note's stem (the vertical line next to the circle) should point upwards if the note is below the middle line of a staff. It should point downwards if the note is above the middle line of a staff. If the note is on the middle line, then the stem may point in either direction. (The only exception to this is for the bonus, and occurs when connecting eighth notes, described later). The stem should begin on the line above/below the circle, and be `6` lines tall.

All types of notes except whole notes have stems. The flag of an eighth note is represented by two forward slashes on different lines (see example notes below).

A filled in note head (for quarter and eighth notes) is represented by `(@)`. An empty note head (for half and whole notes) is represented by `( )`.

Accidentals (sharps, flats, naturals) should be placed as shown in the example notes, with exactly one character between the right side of the accidental and the left side of the note head.

Ledger lines should be used when necessary, and should be `7` characters in length, centered around the note head.

Each note should be `12` characters wide.

Example notes:

```
                                         |_
                                         |_| ( )
                      |                    |------
                      |
------------ ---------|-- ------------ ------------ ------------
                      |
------------ ---------|-- ---|-------- ------------ ------------
      (@)    _|_|_    |      |_
-----|------ _|_|_-( )--- ---|/-(@)--- ------------ ---------|\-
     |        | |              |                             | \
-----|------ ------------ -----|------ ------------ ---------|--
     |                         |                             |
-----|------ ------------ -----|------ ------------ ---------|--
     |                         | /                           |
                               |/                       --(@)--

quarter note half note    eighth note  whole note   eighth note
              sharped      flatted      natural

```

After the 12-character note, leave `2 * 12 - 12 = 12` characters blank (either  or `-` depending on the line) if the note is a quarter note. If the note is a half note, leave `4 * 12 - 12 = 36` characters blank. If the note is a whole note, leave `8 * 12 - 12 = 84` characters blank. Do not add extra characters for eighth notes.

At the end of each measure (96 characters after either the clef or bar line), output a bar line. This is done by going down every character between the uppermost and bottom-most lines (inclusive), and replacing  with `|` and `-` with `+`. (See example output at bottom of question).

At the end of the piece, output the music end by outputting 3 bar lines in a row, but with a space between the first and second. That is:

```
+-++
| ||
+-++
| ||
. ..
. ..

```

Note that sharps, flats, and naturals last until the end of the measure. The natural sign should only be used to cancel out a sharp or flat used earlier in the same measure.

For the purpose of this task, sharps, flats, and naturals only affect a note in one octave, and in one clef (a sharp on A5 does not cause A4 to be sharped, and a flat on C4 in the top staff does not cause C4 in the bottom staff to be flatted).

**Information for the bonus only**

The bonus involves properly connecting eighth notes.

When there are two consecutive eighth notes, aligned to the quarter note beat (in other words, the number of characters before the first eighth note is a multiple of 24), the two eighth notes are to be connected.

Let note **A** be the note farthest from the middle of the staff. If both notes are the same distance from the middle, either note may be note **A**. Let the other note be note **B**.

The direction of *both* stems should be the direction of the stem of note **A**.

The stem of one of the notes should be `6` lines tall (as is the case for stems in general), and the stem of the other note should be extended to the end of the stem of the other note.

The stems should be connected with `_`.

Example connected eighth notes:

```
                                   ___________
                                  |           |
                                  |           |
                                  |           |
                                  |           |       --(@)--
                            |     |           |        |
------------------------ ---|_----|-----------|-- -----|------------------
                            |/ (@)            |        |        |_
------------------------ ---------------------|-- -----|--------|_|-(@)---
      (@)   _|_|_                             |        |          ||
-----|------_|_|_-(@)--- ---------------------|-- -----|-----------|------
     |       | | |                            |        |           |
-----|-----------|------ ---------------------|-- -----|-----------|------
     |           |                            |        |           |
-----|-----------|------ ------------------(@)--- -----|___________|------
     |           |
     |___________|

```

## Example input and output

**Input**:

```
A#4/4 G#4/4 F#4/2 A#4/4 G#4/4 F#4/2 F#4/8 F#4/8 F#4/8 F#4/8 G#4/8 G#4/8 G#4/8 G#4/8 A#4/4 G#4/4 F#4/2
A#3/4 G#3/4 F#3/2 A#3/4 G#3/4 F#3/2 F#3/2 G#3/2 F#3/4 E#3/4 F#3/2

```

**Output**:

```
       ^
      | |            |                                                                                |                                                                                |
------|/-------------|-----------------------|--------------------------------------------------------------+---------|-----------------------|--------------------------------------------------------------+----------___________-------------___________------------|\----------|\----------|\----------|\-+---------|-----------------------|--------------------------------------------------------------+-++
      /              |                       |                       |                                      |         |                       |                       |                                      |         |           |           |           |           | \         | \         | \         | \|         |                       |                       |                                      | ||
-----/|--------------|-----------------------|-----------------------|--------------------------------------+---------|-----------------------|-----------------------|--------------------------------------+---------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|--+---------|-----------------------|-----------------------|--------------------------------------+-++
    / |              |                       |                       |                                      |         |                       |                       |                                      |         |           |           |           |           |           |           |           |  |         |                       |                       |                                      | ||
---/--__----_|_|_----|-----------------------|-----------------------|--------------------------------------+_|_|_----|-----------------------|-----------------------|--------------------------------------+---------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|--+_|_|_----|-----------------------|-----------------------|--------------------------------------+-++
   | /  \   _|_|_ (@)               _|_|_    |                       |                                      |_|_|_ (@)               _|_|_    |                       |                                      |         |           |           |           |  _|_|_    |           |           |           |  |_|_|_ (@)               _|_|_    |                       |                                      | ||
---\-\|-|----|-|--------------------_|_|_-(@)---------------_|_|_----|--------------------------------------+-|-|--------------------_|_|_-(@)---------------_|_|_----|--------------------------------------+_|_|_----|-----------|-----------|-----------|--_|_|_-(@)---------(@)---------(@)---------(@)---+-|-|--------------------_|_|_-(@)---------------_|_|_----|--------------------------------------+-++
    \ | /                            | |                    _|_|_ ( )                                       |                         | |                    _|_|_ ( )                                       |_|_|_ (@)         (@)         (@)         (@)    | |                                            |                         | |                    _|_|_ ( )                                       | ||
------|------------------------------------------------------|-|--------------------------------------------+-------------------------------------------------|-|--------------------------------------------+-|-|--------------------------------------------------------------------------------------------+-------------------------------------------------|-|--------------------------------------------+-++
      |                                                                                |                                                                                |                                                                                |                                                                                | ||
    \_/                                                                                |                                                                                |                                                                                |                                                                                | ||
                                                                                |                                                                                |                                                                                |                                                                                | ||
                                                                                |                                                                                |                                                                                |                                                                                | ||
                                                                                |                                                                                |                                                                                |                                                                                | ||
                                                                                |                                                                                |                                                                                |                                                                                | ||
            _|_|_                                                                                |_|_|_                                                                                |                                                                                |                                                                                | ||
----___-----_|_|_-(@)---------------_|_|_-------------------------------------------------------------------+_|_|_-(@)---------------_|_|_-------------------------------------------------------------------+------------------------------------------------_|_|_-------------------------------------------+------------------------------------------------------------------------------------------------+-++
   /   \ |   | | |                  _|_|_ (@)               _|_|_                                           | | | |                  _|_|_ (@)               _|_|_                                           |_|_|_                                           _|_|_ ( )                                       |_|_|_                                                                                | ||
---\---|---------|-------------------|-|-|------------------_|_|_-( )---------------------------------------+-----|-------------------|-|-|------------------_|_|_-( )---------------------------------------+_|_|_-( )----------------------------------------|-|-|------------------------------------------+_|_|_ (@)---------------_|_|_-------------------------( )---------------------------------------+-++
       | |       |                       |                   | | |                                          |     |                       |                   | | |                                          | | | |                                               |                                          | | | |                  _|_|_ (@)                    |                                          | ||
-------/---------|-----------------------|-----------------------|------------------------------------------+-----|-----------------------|-----------------------|------------------------------------------+-----|-----------------------------------------------|------------------------------------------+-----|-------------------|-|-|-----------------------|------------------------------------------+-++
      /          |                       |                       |                                          |     |                       |                       |                                          |     |                                               |                                          |     |                       |                       |                                          | ||
-----/-----------|-----------------------|-----------------------|------------------------------------------+-----|-----------------------|-----------------------|------------------------------------------+-----|-----------------------------------------------|------------------------------------------+-----|-----------------------|-----------------------|------------------------------------------+-++
                                         |                       |                                          |                             |                       |                                          |     |                                               |                                          |     |                       |                       |                                          | ||
-----------------------------------------------------------------|------------------------------------------+-----------------------------------------------------|------------------------------------------+-----|------------------------------------------------------------------------------------------+-----|-----------------------|-----------------------|------------------------------------------+-++
                                                                                |

```

For the sake of demonstration, in the third measure, the `F#` eighth notes are connected, whereas the `G#` eighth notes are not. Your program should either connect the eighth notes whenever applicable (for the bonus), or leave them all disconnected.

## Other information

* Any amount of trailing whitespace/lines is acceptable.
* There should be no extra whitespace before the clefs, nor whitespace between notes. Any number of blank lines may be emitted before/after the output.
* The bonus for connecting eighth notes is **0.75 * number of bytes of source code**.
* This is , so shortest code wins.

# Answer
> 17 votes
# Python - 8.85... KB (~~9369~~ 9066 B)

HaHA! Fastest gun in the... West?

This is FAR from being properly golfed, but it at least functions. At the moment of posting this, it's the shortest entry, so... yay?

Let me start by saying that I've never golfed anything this big, and I don't even know where to START.

This entry does *not* contain the bonus points yet, but I'd still like to add that before golfing.

I basically wrote a kind of ASCII rendering class that stores the characters that make up each "block" in a 2D format so that any number of different "symbols" could be drawn over the 2D grid. For note blocks, the staff was drawn first, then any staff extending bars as necessary, then the note head, followed by the stem and tail (where applicable) and last the accidental.

When given the following two inputs for trebble and bass clefs:

```
A#4/4 G#4/4 F#4/2 A#4/4 G#4/4 F#4/2 F#4/8 F#4/8 F#4/8 F#4/8 G#4/8 G#4/8 G#4/8 G#4/8 A#4/4 G#4/4 F#4/2
A#3/4 G#3/4 F#3/2 A#3/4 G#3/4 F#3/2 F#3/2 G#3/2 F#3/4 E#3/4 F#3/2

```

The following output results:

```
       ^
      | |            |                                                                                |                                                                                |
------|/-------------|-----------------------|--------------------------------------------------------------+---------|-----------------------|--------------------------------------------------------------+---------------------------------------------------------|\----------|\----------|\----------|\-+---------|-----------------------|--------------------------------------------------------------+-++
      /              |                       |                       |                                      |         |                       |                       |                                      |         |\          |\          |\          |\          | \         | \         | \         | \|         |                       |                       |                                      | ||
-----/|--------------|-----------------------|-----------------------|--------------------------------------+---------|-----------------------|-----------------------|--------------------------------------+---------|-\---------|-\---------|-\---------|-\---------|-----------|-----------|-----------|--+---------|-----------------------|-----------------------|--------------------------------------+-++
    / |              |                       |                       |                                      |         |                       |                       |                                      |         |           |           |           |           |           |           |           |  |         |                       |                       |                                      | ||
---/--__----_|_|_----|-----------------------|-----------------------|--------------------------------------+_|_|_----|-----------------------|-----------------------|--------------------------------------+---------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|--+_|_|_----|-----------------------|-----------------------|--------------------------------------+-++
   | /  \   _|_|_ (@)               _|_|_    |                       |                                      |_|_|_ (@)               _|_|_    |                       |                                      |         |           |           |           |  _|_|_    |           |           |           |  |_|_|_ (@)               _|_|_    |                       |                                      | ||
---\-\|-|----|-|--------------------_|_|_-(@)---------------_|_|_----|--------------------------------------+-|-|--------------------_|_|_-(@)---------------_|_|_----|--------------------------------------+_|_|_----|-----------|-----------|-----------|--_|_|_-(@)---------(@)---------(@)---------(@)---+-|-|--------------------_|_|_-(@)---------------_|_|_----|--------------------------------------+-++
    \ | /                            | |                    _|_|_ ( )                                       |                         | |                    _|_|_ ( )                                       |_|_|_ (@)         (@)         (@)         (@)    | |                                            |                         | |                    _|_|_ ( )                                       | ||
------|------------------------------------------------------|-|--------------------------------------------+-------------------------------------------------|-|--------------------------------------------+-|-|--------------------------------------------------------------------------------------------+-------------------------------------------------|-|--------------------------------------------+-++
      |                                                                                |                                                                                |                                                                                |                                                                                | ||
    \_/                                                                                |                                                                                |                                                                                |                                                                                | ||
                                                                                |                                                                                |                                                                                |                                                                                | ||
                                                                                |                                                                                |                                                                                |                                                                                | ||
                                                                                |                                                                                |                                                                                |                                                                                | ||
                                                                                |                                                                                |                                                                                |                                                                                | ||
            _|_|_                                                                                |_|_|_                                                                                |                                                                                |                                                                                | ||
----___-----_|_|_-(@)---------------_|_|_-------------------------------------------------------------------+_|_|_-(@)---------------_|_|_-------------------------------------------------------------------+------------------------------------------------_|_|_-------------------------------------------+------------------------------------------------------------------------------------------------+-++
   /   \ |   | | |                  _|_|_ (@)               _|_|_                                           | | | |                  _|_|_ (@)               _|_|_                                           |_|_|_                                           _|_|_ ( )                                       |_|_|_                                                                                | ||
---\---|---------|-------------------|-|-|------------------_|_|_-( )---------------------------------------+-----|-------------------|-|-|------------------_|_|_-( )---------------------------------------+_|_|_-( )----------------------------------------|-|-|------------------------------------------+_|_|_-(@)---------------_|_|_-------------------------( )---------------------------------------+-++
       | |       |                       |                   | | |                                          |     |                       |                   | | |                                          | | | |                                               |                                          | | | |                  _|_|_ (@)                    |                                          | ||
-------/---------|-----------------------|-----------------------|------------------------------------------+-----|-----------------------|-----------------------|------------------------------------------+-----|-----------------------------------------------|------------------------------------------+-----|-------------------|-|-|-----------------------|------------------------------------------+-++
      /          |                       |                       |                                          |     |                       |                       |                                          |     |                                               |                                          |     |                       |                       |                                          | ||
-----/-----------|-----------------------|-----------------------|------------------------------------------+-----|-----------------------|-----------------------|------------------------------------------+-----|-----------------------------------------------|------------------------------------------+-----|-----------------------|-----------------------|------------------------------------------+-++
                                         |                       |                                          |                             |                       |                                          |     |                                               |                                          |     |                       |                       |                                          | ||
-----------------------------------------------------------------|------------------------------------------+-----------------------------------------------------|------------------------------------------+-----|------------------------------------------------------------------------------------------+-----|-----------------------|-----------------------|------------------------------------------+-++

```

Here's a working version of the code with some faux input code since this particular python web IDE didn't allow for simulated input or separate files.

**grandstaff.py**

Contains both trebble and bass clef staffs, and handles drawing the barlines between the two.

```
class GrandStaff:
  def __init__(self, trebbleStr, bassStr):
    self.trebbleStr = trebbleStr
    self.bassStr = bassStr
    self.trebbleStaff = Staff("trebble", self.trebbleStr)
    self.bassStaff = Staff("bass", self.bassStr)
    self.bassOffset = 16

    self.lines = {}
    maxmin = self.trebbleStaff.getYExtremes()
    for y in range(maxmin[0], maxmin[1] + 1):
      self.lines[y] = self.trebbleStaff.lines[y]
    maxmin = self.bassStaff.getYExtremes()
    for y in range(maxmin[0], maxmin[1] + 1):
      self.lines[y + self.bassOffset] = self.bassStaff.lines[y]

    for y in range(5, 12):
      self.lines.setdefault(y, [" " for x in range(len(self.trebbleStaff.getLineStr(0)))])
      xpos = 0
      for block in self.trebbleStaff.getBlocks():
        if block.type == "barline":
          self.lines[y][xpos] = '|'
        elif block.type == "finalDoubleBarline":
          for x in [0, 2, 3]:
            self.lines[y][xpos + x] = '|'
        xpos += block.width

  def __str__(self):
    outstr = ""
    maxmin = sorted(self.lines.keys())
    for y in range(maxmin[0], maxmin[-1]):
      self.lines.setdefault(y, [" " for x in range(len(self.trebbleStaff.getLineStr(0)))])
      outstr += ''.join(self.lines[y]) + '\n'

        return outstr

```

**staff.py**

A single staff. Contains an array of "Block" objects that represent notes, barlines, clefs, etc. This class handles the spacing of the notes and insertion of the barlines at the appropriate places.

```
class Staff:
  def __init__(self, clef, inputStr):
    self.clef = clef
    self.inStr = inputStr
    self.lines = {}
    self.__blocks = []
    if clef == "trebble":
      self.__blocks.append(Block("trebbleClef"))
    elif clef == "bass":
      self.__blocks.append(Block("bassClef"))

    notes = inputStr.split(" ");
    measureLength = 0
    for note in notes:
      if measureLength >= 1:
        self.__blocks.append(Block("barline"))
        measureLength -= 1
      parts = note.split("/")
      noteLength = 0
      if len(parts) == 2:
          noteLength += 1 / float(parts[1])
          measureLength += noteLength
      self.__blocks.append(Block("note", note, self.clef))
      for n in range(int(noteLength * 8) - 1):
          self.__blocks.append(Block("staff"))
    self.__blocks.append(Block("finalDoubleBarline"))

    sharps = []
    flats = []
    naturals = []
    for block in self.__blocks:
      if block.type == "note":
        val = block.value

        if block.isSharp:
          if val not in sharps:
            sharps.append(val)
          else:
            block.clearAccidental()
        elif block.isFlat:
          if val not in flats:
            flats.append(val)
          else:
            block.clearAccidental()
        else:
          if val in sharps:
            sharps.remove(val)
            block.setNatural()
          if val in flats:
            flats.remove(val)
            block.setNatural()

      elif block.type == "barline" or block.type == "finalDoubleBarline":
        sharps = []
        flats = []

    maxmin = self.getYExtremes()
    for y in range(maxmin[0], maxmin[1] + 1):
      self.lines[y] = list(self.getLineStr(y))

  def getLineStr(self, lineNum):
    outstr = ""
    for block in self.__blocks:
      outstr += block.getLineStr(lineNum)
    return outstr

  def getYExtremes(self):
    maxmin = [0, 0]
    for block in self.__blocks:
      mm = block.getYExtremes()
      maxmin[0] = mm[0] if mm[0] < maxmin[0] else maxmin[0]
      maxmin[1] = mm[1] if mm[1] > maxmin[1] else maxmin[1]
    return maxmin

  def getBlocks(self):
    return self.__blocks

  def __str__(self):
    maxmin = self.getYExtremes()
    outstr = ""
    for line in range(maxmin[0], maxmin[1] + 1):
      outstr += self.getLineStr(line) + "\n"
    return outstr

```

**block.py**

This class handles the "rendering" (or perhaps composition) of the ASCII text. Inside are the hard-coded symbols such as the trebble and bass clefs, a blank staff, barlines, accidentals, and the necessary pieces to build notes of different durations. These are "drawn" onto a 2D grid of character "pixels" in sequential order to produce the final ASCII block.

```
class Block:

  __staff = [[range(-4, 5, 2),"w",'-']]
  __trebble = [[-6, 7, '^'], [range(-5, 6), 6, '|'], [-5, 8, '|'], [-4, 7, '/'], [-3, 6, '/'], [-2, 5, '/'], [-1, 4, '/'], [0, 3, '/'], [0, range(6,8), '_'], [1, 3, '|'], [1, 5, '/'], [1, 6, ' '], [1, 8, '\\'], [2, 3, '\\'], [2, 5, '\\'], [2, 8, '|'], [3, 4, '\\'], [3, 8, '/'], [6, 4, '\\'], [6, 5, '_'], [6, 6, '/']]
  __bass = [[-4, range(4, 7), '_'], [-3, 3, '/'], [-3, 7, '\\'], [range(-3, 0, 2), 9, '|'], [-2, 3, '\\'], [range(-2, 0), 7, '|'], [0, 7, '/'], [1, 6, '/'], [2, 5, '/']]
  __sharp = [[range(-1, 1), range(0, 5), '_'], [range(-1, 2), range(1, 4, 2), '|']]
  __flat = [[range(-2, 1), 3, '|'], [-1, 4, '_'], [0, 4, '/']]
  __natural = [[range(-1, 1), 2, '|'], [range(-1, 1), 3, '_'], [range(0, 2), 4, '|']]
  __noteOpen = [[0, 6, '('], [0, 7, ' '], [0, 8, ')']]
  __noteClosed = [[0, 6, '('], [0, 7, '@'], [0, 8, ')']]
  __stemUp = [[range(-6, 0), 9, '|']]
  __stemDown = [[range(1, 7), 5, '|']]
  __eighthTailUp = [[-6, 10, '\\'], [-5, 11, '\\']]
  __eighthTailDown = [[6, 6, '/'], [5, 7, '/']]
  __barline = [[range(-4, 5), 0, '+'], [range(-3, 4, 2), 0, '|']]
  __finalBarline = [[range(-4, 5, 2), [0, 2, 3], '+'], [range(-3, 4, 2), [0, 2, 3], '|'], [range(-4, 5, 2), 1, '-']]
  __staffExtender = [[0, range(4, 11), '-']]

  def __init__(self, type, notestr = "", clef = "trebble"):
    if type == "note":
      self.clef = clef
      self.notestr = notestr.upper().split('/')[0]
      self.duration = int(notestr.upper().split('/')[1])
      self.isSharp = True if notestr[1] == '#' else False
      self.isFlat = True if notestr[1] == 'b' else False
      self.isNatural = False;
      self.__clefCallibration = {"trebble":{"A":1,"B":0,"C":6,"D":5,"E":4,"F":3,"G":2,"octave":4}, "bass":{"A":-4,"B":-5,"C":1,"D":0,"E":-1,"F":-2,"G":-3,"octave":3}}
      self.value = self.__clefCallibration[self.clef][self.notestr[0]] + ((self.__clefCallibration[self.clef]["octave"] - int(self.notestr[-1])) * 7)

    self.lines = {}
    self.type = type

    self.__drawBlock()

  def __drawBlock(self):
    self.lines = {}
    if self.type == "note":
      self.width = 12
      self.__draw(self.__staff)

      for y in range(6, self.value + 1, 2):
        self.__draw(self.__staffExtender, y)
      for y in range(-6, self.value - 1, -2):
        self.__draw(self.__staffExtender, y)

      if self.duration in [1, 2]:
        self.__draw(self.__noteOpen, self.value)
      else:
        self.__draw(self.__noteClosed, self.value)

      if self.duration != 1:
        if self.value < 0:
          self.__draw(self.__stemDown, self.value)
          if self.duration == 8:
            self.__draw(self.__eighthTailDown, self.value)
        else:
          self.__draw(self.__stemUp, self.value)
          if self.duration == 8:
            self.__draw(self.__eighthTailUp, self.value)

      if self.isSharp:
        self.__draw(self.__sharp, self.value)
      elif self.isFlat:
        self.__draw(self.__flat, self.value)
      elif self.isNatural:
        self.__draw(self.__natural, self.value)

      # self.__draw(__staffExtender, self.value)
    elif self.type == "staff":
      self.width = 12
      self.__draw(self.__staff)
    elif self.type == "barline":
      self.width = 1
      self.__draw(self.__barline)
    elif self.type == "finalDoubleBarline":
      self.width = 4
      self.__draw(self.__finalBarline)
    elif self.type == "trebbleClef":
      self.width = 12
      self.__draw(self.__staff)
      self.__draw(self.__trebble)
    elif self.type == "bassClef":
      self.width = 12
      self.__draw(self.__staff)
      self.__draw(self.__bass)

  def __draw(self, data, yOffset = 0):
    for char in data:
        self.__drawChunk(char, yOffset)

  def __drawChunk(self, char, yOffset = 0):
      xrng = []
      yrng = []
      drawChr = char[2]

      if type(char[0]) == int:
        yrng = [char[0]]
      elif type(char[0]) == list:
        yrng = char[0]
      else:
        print("ERROR: invalid y range input")

      if type(char[1]) == str:
        if char[1] == 'w':
          xrng = range(self.width)
      elif type(char[1]) == int:
        xrng = [char[1]]
      elif type(char[1]) == list:
        xrng = char[1]
      else:
        print("ERROR: invalid x range input")

      yrng = [y + yOffset for y in yrng]

      for y in yrng:
        self.lines.setdefault(y,[" " for i in range(self.width)])
        for x in xrng:
          self.lines[y][x] = drawChr

  def getLineStr(self, lineNum):
    return "".join(self.lines.setdefault(lineNum, [" " for i in range(self.width)]))

  def getYExtremes(self):
    k = sorted(self.lines.keys())
    return [k[0], k[-1]]

  def setSharp(self):
    self.isSharp = True
    self.isFlat = False
    self.isNatural = False
    self.__drawBlock()

  def setFlat(self):
    self.isSharp = False
    self.isFlat = True
    self.isNatural = False
    self.__drawBlock()

  def setNatural(self):
    self.isSharp = False
    self.isFlat = False
    self.isNatural = True
    self.__drawBlock()

  def clearAccidental(self):
    self.isSharp = False
    self.isFlat = False
    self.isNatural = False
    self.__drawBlock()

  def __str__(self):
    strOut = ""
    first = sorted(self.lines.keys())[0]
    last = sorted(self.lines.keys())[-1]
    for line in range(first, last + 1):
        strOut += self.getLineStr(line) + "\n"
    return strOut

```

**main.py**

This class simply "runs" the program by creating an instance of GrandStaff, passing it the given string inputs, and printing it's string value.

```
import sys
from block import *
from grandstaff import *
from staff import *

print (GrandStaff(sys.argv[1],sys.argv[2]))

```

---
Tags: code-golf, ascii-art, music
---


title: Mirror programs

text:
# Question
Title: Mirror programs
Here is your task, should you choose to accept it: Output (through STDOUT, or whatever is most convenient) some `n` by `m` ASCII art that has at least one line of symmetry and is non-empty. Example:

```
HiiH
iooi
iooi
H!!H

```

This is a 4x4 example output.

(Note: I define an ASCII character to be in the ASCII range 32-126 plus newlines and spaces. *No tabulators*.)

Here's the catch: Your program must also reflect across these same axes AND must be a rectangle in shape. (The output and the input are not necessarily the same width/length). Here is an example in JavaScript:

```
console.log("HiH")//("HiH")gol.elosnoc;
console.log("JvJ")//("JvJ")gol.elosnoc;
console.log("...")//("...")gol.elosnoc;

```

The source code has one line of symmetry (vertical) and the output has one line of symmetry: vertical.

```
HiH
JvJ
...

```

This is a , so the highest-voted answer on THIS DATE:

```
3:00 PM
Saturday, September 27, 2015
Eastern Time (ET)

```

will be the winner.

# TL;DR

Write a program with the same axes of reflections as the output, of which is at least one. The output must have side lengths greater than one and must have at least one non-whitespace character.

# EDIT

If a character has a mirrored version (e.g. `(` and `)`), then it should be used instead of itself. Example:

```
[>Hello!\} => {/!olleH<]

```

# Why this question is *not* a duplicate

Said question wished to produce a quine which was the same, forth and back; my challenge is different in two ways. One, it does not necessarily have to be forth and back (up and down, right and left, e.g.). Two, I am not asking for a quine.

# Answer
# Brainfuck, 103 bytes

I made you a sandwich.

```
---+++++++++++++---
[>+++>+<<->>+<+++<]
>...>-.<...>.-<...<
[>+++>+<<->>+<+++<]
---+++++++++++++---

```

Output:

```
***
***
***

```
> 7 votes

# Answer
## Pyth, 29 bytes

```
FG[\@\@)pGpG*0"0*GqGq(@/@/]GF

```

Demo

I'm assuming that one-liners are okay, otherwise there is an easy fix.
> 4 votes

---
Tags: popularity-contest, ascii-art
---


title: Code me some golf

text:
# Question
Title: Code me some golf
**If you haven't played golf before, here's a list of golf-related terms I use in this question**

* *Shot*, also called a *stroke*: Every time the ball is hit, this is a shot.
* *Hole*: A golf course is split into holes, in which the goal is to hit a ball from one designated location to another in as few shots as possible.
* *Tee*: Where you start a hole.
* *Pin* or *Flag*: Where you finish a hole
* *Fairway*, *Rough*, *Water*, and *Green*: Features on a golf course that affect how one plays the ball in real life. (How they affect the program is specified below)

---

I'm going out to play golf tomorrow, and I find that sometimes, I have trouble figuring out what club to use to hit a certain yardage. So I decided to write down my clubs and their yardages per shot.

**First Assumption: All holes are due north of their tee boxes.**

All of these yardages measure the possibilities for how far north the ball travels. The ball will travel a random integer distance between the bounds specified for each club (inclusive).

As a master golfer, none of my shots have any horizontal shift. This means that all of my shots go in a straight line directly at the flag.

```
Club #     Club        Yardage
1          Driver      300-330
2          3-Wood      270-299
3          5-Wood      240-269
4          3-Iron      220-239
5          4-Iron      200-219
6          5-Iron      180-199
7          6-Iron      160-179
8          7-Iron      140-159
9          8-Iron      120-139
10         9-Iron      100-119
11         P-Wedge     80-99
12         S-Wedge     50-79
13         L-Wedge     0-49
14         Putter      (only on green)

```

As a person who enjoys programming, I decide that I want to model a round of golf and set a goal for how well I want to do tomorrow. However, like any amateur programmer, after ten minutes, I gave up and asked for help on Stack Overflow (just kidding). Here are some more data about the course.

**Second Assumption: Hole Geography**

* All numbers that describe distances on the course are integers.
* Each hole is a straight line. The straight line distance between each hole and the pin (the end of the hole) is `Length`.
* Fairways are segments with length defined by `flen`. The value listed for `flen` is the range of yardages north from the tee where fairway is.
* Water hazards are segments that have length defined by `wlen`, which has the same properties as `flen`.
* The green has a length defined by `glen`.
* All parts of the course that are not fairway, water, or green are rough.

Here is a chart describing each hole on the course.

```
Hole #     Length      flen               wlen        glen
1          401         54-390                         391-425
2          171                            1-165       166-179
3          438         41-392             393-420     421-445
4          553         30-281,354-549     282-353     550-589
5          389         48-372                         373-404
6          133                                        125-138
7          496         37-413             414-484     484-502
8          415         50-391                         392-420
9          320         23-258             259-303     304-327

```

**How to play Golf** (for this program)

* Always aim exactly at the flag.
* Hit the ball as close to the pin as possible, trying to keep the ball on the fairway or (preferably) on the green.
* When you land a shot in the water, your next shot must be played from the same place as the shot that went into the water.
* Once the ball lands on the green, only the putter can be used. If the ball lands strictly more than 5 yards from the pin, then I putt twice. Otherwise, I putt once.
* It is possible to hit a shot past the pin.

**Scoring**

My score on a hole is the number of shots I take, plus one stroke for every time I land in rough or the water.

**The program**

Okay, that was a lot of rules, now let's talk about the program.

The course should be defined as above *in the program*, because the course is constant. Different golfers, however, have different distances for each shot, so the input to STDIN should be a set of ranges of yardages, arranged in increasing order of club number and separated by commas (with no whitespace).

The output should be how I "play" the round of golf. The hold number should be specified at the beginning of each line as `Hole #:` where `#` is the current hole. Each shot that is not a putt is of the following form: `{club,distance of shot,condition of ball,distance to pin}`. The details of the shot should be separated by commas but no whitespace in the above order. The shots themselves should be written in order of how they are played and separated by a space. Once the ball lands on the green, the program should print how many putts I take, in the format `{# putts}`. At the end of each line, the number of shots I took on the hole should be separated from the other shots by a space and printed as `(#)`. Each hole should be on its own line and written in order. Finally, on the last (tenth) line of the program, the total number of shots for the round should be printed as `Total: # shots`.

There is no set "strategy" that your program is required to take. You can write a program with any strategy you want. Example strategies include maximizing the percent chance of landing on the green and maximizing the distance of each shot until reaching the hole.

SAMPLE INPUT

```
300-330,270-299,240-269,220-239,200-219,180-199,160-179,140-159,120-139,100-119,80-99,50-79,0-49

```

SAMPLE OUTPUT

```
Hole 1: {Driver,324,Fairway,77} {S-Wedge,70,Green,7} {Two putts} (4)
Hole 2: {6-Iron,162,Water,171} {6-Iron,168,Green,3} {One putt} (4)
Hole 3: {Driver,301,Fairway,137} {8-Iron,131,Green,6} {Two putts} (4)
Hole 4: {3-Wood,288,Water,553} {3-Wood,276,Fairway,277} {3-Wood,291,Green,14} {Two putts} (6)
Hole 5: {Driver,322,Fairway,67} {S-Wedge,62} {One putt} (3)
Hole 6: {8-Iron,120,Rough,18} {L-Wedge,10,Green,8} {Two putts} (5)
Hole 7: {Driver,325,Fairway,171] {6-Iron,170,Green,1} {One putt} (3)
Hole 8: {Driver,306,Fairway,109} {9-Iron,100,Green,9} {Two putts} (4)
Hole 9: {Driver,308,Green,12} {Two putts} (3)
Total: 36 shots

```

---

I'll admit, this is a rather ambitious challenge for a first post on CG.SE, so I'd be glad to talk about how to improve this challenge in comments. Thank you for your help.

# Answer
# Python 2.7: ~~43~~ 40.5 shots average

This is my first post here so bear with me.

Since the poster was thinking of treating this like a programming challenge, not code golf, I tackled it as more a programming challenge. I attempted to keep my solution and shot logic simple but it turned out more ugly as things got complicated quickly.

## My Code

Some things to think of while reading: the program creates a list of clubs used called 'clubs', and a list called 'distances' that is distance the ball has traveled from the tee, hlen is the length of the hole, d1s is the distance each shot travels.

First I define the course. Each fairway, water, and green length had to be defined so later the program could check the condition of the ball, so I added non-integers values for the parts of the course that did not exist.

```
from random import randint
import numpy as np

#Hole      Length     flen               wlen           glen    Name
hole1 = [    401,     54, 390,       390.5, 390.5,    391, 425, 'Hole 1']
hole2 = [    171,    0.5, 0.5,           1, 165,      166, 179, 'Hole 2']
hole3 = [    438,     41, 392,         393, 420,      421, 445, 'Hole 3']
hole4 = [    553,     30, 549,         282, 353,      550, 589, 'Hole 4']
hole5 = [    389,     48, 372,         1.5, 1.5,      373, 404, 'Hole 5']
hole6 = [    133,    0.5, 0.5,         1.5, 1.5,      125, 138, 'Hole 6']
hole7 = [    496,     37, 413,         414, 484,      484, 502, 'Hole 7']
hole8 = [    415,     50, 391,         1.5, 1.5,      392, 420, 'Hole 8']
hole9 = [    320,     23, 258,         259, 303,      304, 327, 'Hole 9']

holes = [hole1, hole2, hole3, hole4, hole5, hole6, hole7, hole8, hole9]

```

Here I defined the main logic for choosing a club. The program attempts to maximize distance by choosing the driver for all lengths greater than the max driver distance and chooses a club with range that contains the distance to the hole otherwise. This requires the range provides by the club input to be continuous, i.e. no gaps in shot distance. A realistic requirement since one can hit a club without a full backswing to limit the distance of their shot to the maximum distance of the next most powerful club.

```
def stroke(distance):
    Length = abs(hlen - distance)
    if Length >= Driver_a:
        club = 'Driver'
        d = randint(Driver_a,Driver_b)
    elif Length >= Wood3_a and Length <= Wood3_b:
        club = '3-Wood'
        d = randint(Wood3_a,Wood3_b)
    elif Length >= Wood5_a and Length <= Wood5_b:
        club = '5-Wood'
        d = randint(Wood5_a,Wood5_b)
    elif Length >= Iron3_a and Length <= Iron3_b:
        club = '3-Iron'
        d = randint(Iron3_a,Iron3_b)
    elif Length >= Iron4_a and Length <= Iron4_b:
        club = '4-Iron'
        d = randint(Iron4_a,Iron4_b)
    elif Length >= Iron5_a and Length <= Iron5_b:
        club = '5-Iron'
        d = randint(Iron5_a,Iron5_b)
    elif Length >= Iron6_a and Length <= Iron6_b:
        club = '6-Iron'
        d = randint(Iron6_a,Iron6_b)
    elif Length >= Iron7_a and Length <= Iron7_b:
        club = '7-Iron'
        d = randint(Iron7_a,Iron7_b)
    elif Length >= Iron8_a and Length <= Iron8_b:
        club = '8-Iron'
        d = randint(Iron8_a,Iron8_b)
    elif Length >= Iron9_a and Length <= Iron9_b:
        club = '9-Iron'
        d = randint(Iron9_a,Iron9_b)
    elif Length >= Pwedge_a and Length <= Pwedge_b:
        club = 'P wedge'
        d = randint(Pwedge_a,Pwedge_b)
    elif Length >= Swedge_a and Length <= Swedge_b:
        club = 'S wedge'
        d = randint(Swedge_a,Swedge_b)
    elif Length >= Lwedge_a and Length <= Lwedge_b:
        club = 'L wedge'
        d = randint(Lwedge_a,Lwedge_b)
    else : print 'stroke error'
    return club, d

```

Next, I define a put function that two putts for all lengths greater than 5 yards to the hole and one putt for 5 and less. I also include an option for hitting the ball directly into the hole called 'chip in'.

```
def putt(distance):
    Length = abs(hlen - distance)
    if Length > 5:
        club = '2 putts'
    elif Length == 0:
        club = 'chip in'
    else:
        club = '1 putt'
    return club

```

Here is where the strategy gets a little funky. In order to keep it simple and also prevents getting stuck in a loop of driving into water only to drop the ball at the location of the previous shot and drive into the water again, I actually backtrack, hitting the ball backward with the sand wedge and then have the code evaluate the shot again this time hopefully shooting just in front of the water so the next shot can clear it. This strategy is penalized by the rough penalty but is effective for clearing water.

```
def water():
    club = 'S wedge'
    d = randint(50,79)
    return club, d

```

This program counts the number of strokes per hole after that hole has been played. It adds the penalties for the shots in the rough and adds the penalties for hitting into the water by summing a array called water that is appended after each water shot. This takes advantage of the fact that fairway always leads to water or to the green for every hole in the course. It would have to be changed for courses that contained rough in the middle of the fairway.

```
def countstrokes(clubs, distances, waters):
    distances = np.array(distances)
    mask1 = distances < flen1
    mask2 = distances > grn2
    extra = sum(mask1*1)+sum(mask2*1) + sum(waters)
    if clubs[-1] == 'chip in' : strokes = len(clubs)-1+extra
    elif clubs[-1] == '2 putts' : strokes = len(clubs) +1+extra
    elif clubs[-1] == '1 putt' : strokes = len(clubs)+extra
    else : print 'strokes error'
    return strokes

```

After the main code runs, condition looks at the distances the ball was at during the hole and reports the condition of the ball. I ran into one issue with condition because of the way I treated hitting the ball into the water in the main program. In the program, if the ball was hit into the water, it was immediately moved back to the location of where the shot was hit. The distance was recorded after the ball is moved back so the condition of the ball cannot be ‘water’. If you hit the ball off the tee on hole 4 into the water, the program prints the distance you hit the ball and the club but the length to the hole will remain unchanged and the condition will be 'rough' since the ball is dropped at 0 distance which is in the rough. You can uncomment a print 'water' flag if you want to be told how many times the ball is hit into the water before each hole.

```
def condition(distances):
    conditions=[]
    for distance in distances:
        if distance >= grn1 and distance <= grn2:
            conditions.append('green')
        elif distance >= flen1 and distance <= flen2:
            conditions.append('fair')
        else:
            conditions.append('rough')
    return conditions

```

Here is the main part of the code which loads the holes and plays the game. After initializing some conditions the code runs 'stroke' hitting the ball towards the hole, including reverse if the hole was overshot, until either water or green is encountered. If water is encountered, it adds to a penalty counter and runs the program water and after moving the ball back to the location it was hit from. If the green is encountered, put is called and the hole is terminated. After the distances and clubs are analyzed to determine the condition of each shot and the shots are tallied.

```
def golf(driver_a, driver_b, wood3_a, wood3_b, wood5_a, wood5_b, iron3_a, iron3_b, iron4_a, iron4_b, iron5_a, iron5_b, iron6_a, iron6_b, iron7_a, iron7_b, iron8_a, iron8_b, iron9_a, iron9_b, pwedge_a, pwedge_b, swedge_a, swedge_b, lwedge_a, lwedge_b):
    global Driver_a, Driver_b, Wood3_a, Wood3_b, Wood5_a, Wood5_b, Iron3_a, Iron3_b, Iron4_a, Iron4_b, Iron5_a, Iron5_b, Iron6_a, Iron6_b, Iron7_a, Iron7_b, Iron8_a, Iron8_b, Iron9_a, Iron9_b, Pwedge_a, Pwedge_b, Swedge_a, Swedge_b, Lwedge_a, Lwedge_b
    Driver_a, Driver_b, Wood3_a, Wood3_b, Wood5_a, Wood5_b, Iron3_a, Iron3_b, Iron4_a, Iron4_b, Iron5_a, Iron5_b, Iron6_a, Iron6_b, Iron7_a, Iron7_b, Iron8_a, Iron8_b, Iron9_a, Iron9_b, Pwedge_a, Pwedge_b, Swedge_a, Swedge_b, Lwedge_a, Lwedge_b = driver_a, driver_b, wood3_a, wood3_b, wood5_a, wood5_b, iron3_a, iron3_b, iron4_a, iron4_b, iron5_a, iron5_b, iron6_a, iron6_b, iron7_a, iron7_b, iron8_a, iron8_b, iron9_a, iron9_b, pwedge_a, pwedge_b, swedge_a, swedge_b, lwedge_a, lwedge_b
    totals =[]
    for hole in holes:
        distance = 0
        strokes = 0
        clubs = []
        distances = []
        d1s = []
        waters=[]
        global hlen, flen1, flen2, wtr1, wtr2, grn1, grn2
        hlen, flen1, flen2, wtr1, wtr2, grn1, grn2, name = hole
        while True:
            club1, d1 = stroke(distance)
            clubs.append(club1)
            if distance > hlen:
                d1 = -d1
            distance = distance + d1
            d1s.append(d1)
            if distance >= wtr1 and distance <= wtr2:
                #print 'water'
                waters.append(1)
                distance = distance - d1
                distances.append(distance)
                club1, d1 = water()
                if distance < wtr1:
                    d1 = - d1
                distance = distance + d1
                d1s.append(d1)
                clubs.append(club1)
            distances.append(distance)
            if distance >= grn1 and distance <= grn2:
                club1 = putt(distance)
                clubs.append(club1)
                break
        strokes =  countstrokes(clubs, distances, waters)
        totals.append(strokes)
        conditions = condition(distances)
        shots = len(d1s)
        print name, ':',
        for x in xrange(0,shots):
            print '{', clubs[x], ',', d1s[x],',', conditions[x],',', hlen-distances[x], '}',
        print '{',clubs[-1], '}', '{',strokes ,'}'
    print 'Total:', sum(totals), 'shots'
    return sum(totals)

```

The code is run like

```
golf(300,330,270,299,240,269,220,239,200,219,180,199,160,179,140,159,120,139,100,119,80,99,50,79,0,49)

```

and the out looks like this:

```
Hole 1 : { Driver , 308 , fair , 93 } { P wedge , 96 , green , -3 } { 1 putt } { 3 }
Hole 2 : { 6-Iron , 166 , green , 5 } { 1 putt } { 2 }
Hole 3 : { Driver , 321 , fair , 117 } { 9-Iron , 105 , green , 12 } { 2 putts } { 4 }
Hole 4 : { Driver , 305 , rough , 553 } { S wedge , -62 , rough , 615 } { Driver , 326 , fair , 289 } { 3-Wood , 293 , green , -4 } { 1 putt } { 8 }
Hole 5 : { Driver , 323 , fair , 66 } { S wedge , 73 , green , -7 } { 2 putts } { 4 }
Hole 6 : { 8-Iron , 125 , green , 8 } { 2 putts } { 3 }
Hole 7 : { Driver , 314 , fair , 182 } { 5-Iron , 181 , green , 1 } { 1 putt } { 3 }
Hole 8 : { Driver , 324 , fair , 91 } { P wedge , 91 , green , 0 } { chip in } { 2 }
Hole 9 : { Driver , 317 , green , 3 } { 1 putt } { 2 }
Total: 31 shots

```

This was one the lowest score of many trials, with an absolute lowest of 26 in 100,000 runs. But still under a typical par of 34-36 even with 8 strokes on hole 4.

I'll include the code I used to find the distribution of games with the above specified clubs.

```
import matplotlib.pyplot as plt
class histcheck(object):

    def __init__(self):
        self = self

    def rungolf(self, n=10000):
        results=[]
        for x in xrange(0,n):
            shots = golf(300,330,270,299,240,269,220,239,200,219,180,199,160,179,140,159,120,139,100,119,80,99,50,79,0,49)
            results.append(shots)
        self.results = results

    def histo(self, n=20):
        plt.figure(figsize=(12,12))
        plt.hist(self.results, bins=(n))
        plt.title("Histogram")
        plt.xlabel("Shots")
        plt.ylabel("Frequency")
        plt.show()

```

Running

```
play = histcheck()
play.rungolf()
play.hist()

```

gives the following histogram

and the mean and median can be found using

```
np.mean(play.results)
np.meadian(play.results)

```

a mean of about 43 and a median of 41. Not too bad for 9 holes with simple shot optimization.

## It is all yours now

Go ahead and copy and tweak my program and evaluate it using my tools in order to lower the average number of shots. Let me know if there is anything scenario I didn't account for or go ahead and make a golfed version. I think that the best program would be one that returned the lowest average shots for a number of club inputs. My code isn't the best option for that but I thought I'd get the ball rolling.

## Update

```
def water():
    if clubs[-1] =='S wedge':
        club = 'S wedge'
        d = randint(50,79)
    elif clubs[-1] !='S wedge':
        club = 'S wedge'
        d = -randint(50,79)
    else: print 'water error'
    return club, d

```

By changing the water logic so that it attempts to hit the ball forward by a small amount after encountering water instead of backwards if the previous club used was not the sand wedge, it improved the mean to 40.5 and the median to 39 after testing with *one million* runs. Minimum of 23, maximum of 135. Sometimes you get lucky, sometimes you don't. Check out the new histogram.
> 10 votes

---
Tags: code-golf, simulation
---


# Question
Title: Fastest gun of the west, king of the hill challenge
This is a King of the Hill challenge in a round robin. It's a battle to find the best gunman of the west!

To be able to compete in this contest you need to make two functions. The first one sets the attributes of your gunman and the second is the main logic function for the gunman.

# Attribute Function

```
function () {

    var bot = {
        name: "testBot",
        numbOfBullets: 7,
        reloadSpeed: 1,
        shotsPerTurn: 1,
        moveSpeed: 2
    }
    return bot
}

```

The attribute function includes 5 variables that you will need to set according to some rules (with the exception of `name` that can be any string). You must spend a total of exactly 15 points on your gunman -- gunmen that do not spend all 15 points are not eligible. Here is how the attributes work:

* **`numbOfBullets`** \- defines how many bullets your gun holds.

The initial and minimum value of `numbOfBullets` is 1. Each additional bullet costs 1 point with the maximum being 16 bullets with 15 points spent.
* **`reloadSpeed`** \- defines how many turns your gunman needs to reload his gun after he ran out of bullets.

The base and maximum value is 4 with the minimum being 1. Decreasing this attribute by 1 costs 2 points.
* **`shotsPerTurn`** \- defines how many times your gunman can shoot in one turn.

The base and minimum value is 1. Each increase by 1 costs 3 points so you can have a maximum of 6 shots per round with 15 points spent. Raising this attribute above `numbOfBullets` is counter productive since you can't shoot more bullets then your gun can hold.
* **`moveSpeed`** \- defines how many spaces your gunman can run in one turn.

The base and minimum value is 1. Each increase by 1 costs 3 points with a maximum of 6 speed with 15 points spent. The gunman can run either left or right every turn up to a maximum of his move speed. He can also stand still which gives him a bonus (more on this later).

The example function above has 6 points spend on bullets, 6 points spend on reload speed and 3 points spend on movement.

# Main function

```
function main(bulletsLeft, yourShots, enemyShots, yourMovement, enemyMovement) {

    var shots = [];
    shots.push(Math.floor((Math.random() * 24) + 1));
    var move = yourMovement[yourMovement.length - 1] + 2
    var play = [];
    play.shots = shots;
    play.move = move;
    play.reload = false;
    return play;
}

```

**Parameters:**

* `bulletsLeft`, number of bullets left in your gun
* `yourShots`, this is a array of arrays of all the past positions your gunman has fired at.

Example for a gunman who can shoot 1 bullet per round:

```
[[12],[4],[22],...]

```

Example for a gunman who can shoot 3 bullets per round:

```
[[12,13,14],[11,15,16],[9,14],...]

```
* `enemyShots` \- same as above but for your enemy
* `yourMovement` \- an array of all your past movement positions
* `enemyMovement`, same as above but for your enemy

**What you need to return:**

You are required to return a variable which has 3 attributes:

* `shots` \- an array of numbers which determine at which space/s your gunman will shoot
* `move` \- a single number that determines to what space your gunman will try to move to
* `reload` \- a true/false value with which you can make your gunman reload

# The Duel

The contest follows a round robin 1 versus 1 system. Each gunman has 50 rounds against every other gunman. A round lasts until someone is hit by a bullet or until 66 turns have passed (a turn is when both players have shot).

The gunman can earn 2 points by killing their opponent, 1 point if they both die in the same turn or 0 points if they reach the 66 turns limit. The shooting field is 24 spaces width (1-24 inclusive). To hit a player and win a round you need to shoot at the same space as he is currently standing on.

Here is a step by step guide on how a duel works. This also covers all invalid commands and special rules:

* At the start of each duel both players are put on space 12 and their revolvers are fully loaded
* The main function is called and the gunman make their first move command and choose where they want to shoot
* First the gunmen move to their new location. If any invalid input is made at the move command (positions lower then 1 or higher then 24 or they moved more spaces then they are allowed too) they stay at the same position.
* Next reloading is checked, if you ran out of bullets the previous turn or you called reloading yourself your gunman goes into the reload cycle. He is reloading for as many turns as you set your `reloadSpeed` value. If you decided to stand still (returning the same space integer as you where standing on before or just returning a invalid value) you reload counter goes down for 2 turns instead of one.
* Now comes checking your shooting values, every turn you can enter as many shooting location as you like they will always be cut off to the actual valid amount which is determined by: The number of shots per turn and the number of bullets in your revolver (whichever is lower). Your `shotsPerTurn` value is increased by 1 if you decide to stand still this turn, so you can make a extra shot if you decide to stand still. If you are in the reload cycle you have 0 shots.
* Now comes the actual shooting, there are 2 ways this can go down. If both gunman have the same movespeed stat then they both shoot at the same time and can both kill each other at the same time. In the case that they have different movespeed stats the bot with the higher movespeed stat starts shooting first and if he kills his opponent he wins this round. If the gunman can shoot one or more bullets in one round then it follows the same rules as above except in more cycles as a example: Lets say that bot1 has 3 bullets and is faster and bot 2 has 2 bullets then it would go like this:

```
Bot1 shoots, Bot2 shoots cycle 1
Bot1 shoots, Bot2 shoots cycle 2
Bot1 shoots              cycle 3

```

This would look the same if they had the same movespeed only that if now Bot1 hit Bot2 in the same cycle Bot2 could also hit Bot1 and it would be a tie.

# RULES

First I am copying some rules from Calvin's Hobbies' entry that also apply here.

**When declaring a new JavaScript variable, you must use the var keyword.** This is because a variable declared without var becomes global rather than local, so it would be easy to accidentally (or intentionally) mess with the controller or communicate freely with other players. It has to be clear that you aren't trying to cheat.

When declaring functions it is best to use the var keyword as well, i.e. use `var f = function(...) {...}` instead of `function f(...) {...}.` I'm not entirely sure why, but sometimes it appears to make a difference.

In your code you may not...

* attempt to access or modify the controller or other player's code.
* attempt to modify anything built into JavaScript.
* make web queries.
* do otherwise malicious things.

My additional rules:

* The users can create as many gunman as they want and change their functions for any period of time
* I will remove any entry from the game that either takes a excessive amount of time or tries to cheat in any way that I see fit
* The names of the attributes that your function need to return has to be the same as in the examples with the same structure!

Your answer should be in this format, the first function being the attribute function and the second being the logic function. Notice that I used an exclamation mark because if you just make new lines between code blocks the parser wont see two different code blocks so you have to use any symbol(just use a exclamation mark) to seperate them:

```
var bot = {
    name: "testBot",
    numbOfBullets: 7,
    reloadSpeed: 1,
    shotsPerTurn: 1,
    moveSpeed: 2
}
return bot

```

```
var shots = []
var testBot_moveUp = true
if(Math.random() * 2 > 1)
    testBot_moveUp = false
shots.push(Math.floor((Math.random() * 24) + 1))
var move = 0
if (testBot_moveUp)
    move = yourMovement[yourMovement.length - 1] + 2
else
    move = yourMovement[yourMovement.length - 1] - 2
move = 12
var play = []
play.shots = shots
play.move = move
play.reload = false
return play

```

And here is the controller: GAME CONTROLLER. Just open the link and wait for the bots to load, then select which one you want in the fight (probably all) and press the start button.

I also put in a testbot as my answer which will compete, it also serves as a example on how the structure of the answer should look like. As a note, if you make a small mistake and edit your answer stackexchanges algorithm might not pick it up right away and the site that the controller uses which is generated by stackexchange isnt updated(but will later or if you make bigger changes which i suggest doing, just add some text at the end). Here is the site: codelink

# Answer
# Pandarus

```
var bot = {
    name:"Pandarus",
    numbOfBullets: 2,
    reloadSpeed: 3,
    shotsPerTurn: 1,
    moveSpeed: 5
}
return bot

```

```
var myPos;
if(yourMovement.length > 0)
{
    myPos = yourMovement[yourMovement.length - 1];
}
else
{
    myPos = 12;

}
var EnemyPos;
if(enemyMovement.length>0) {
    EnemyPos = enemyMovement[enemyMovement.length - 1];
}
else
{
    EnemyPos = 12;
}

var play = {
    shots: [
    ],
    reload: true,
    move: 12
};
if (bulletsLeft < 1)
{
    //Reload
    play.reload = true;
    play.shots = [
    ];
}
else
{
    //FIRE!!!
    play.reload = false;
    var enemyMoveSum = 0;
    for (var i = 0; i < enemyMovement.length; i++)
    {
        var MoveSinceLast;
        if (i == 0)
        {
            MoveSinceLast = enemyMovement[i] - 12;
        }
        else
        {
            MoveSinceLast =enemyMovement[i] - enemyMovement[i-1];
        }

        enemyMoveSum += Math.abs(MoveSinceLast);
    }

    var enemyAvgMove;
    if (enemyMovement.length > 0)
    {
        enemyAvgMove = Math.round(enemyMoveSum / enemyMovement.length);
    }
    else
    {
        enemyAvgMove = 0;
    }

    var LeftShot = EnemyPos - enemyAvgMove;
    var RightShot = EnemyPos + enemyAvgMove;

    if (RightShot > 24 ||( (LeftShot>0) && (Math.random()*2 < 1)))
    {
        play.shots.push(
            LeftShot
        );
    }
    else
    {
        play.shots.push(
            RightShot
        );
    }
}

var MyMove = myPos;
do
{
    var move = Math.floor(Math.random() * 10) - 5;
    if(move == 0)
    {
        move = 5;
    }
    MyMove = myPos + move;
}
while (MyMove<1 || MyMove > 23)

play.move = MyMove;

return play;

```

Pandarus relies on his speed to get out the way of the bullets, and uses the enemies previous movements to guess where they are going to go.
> 6 votes

# Answer
## A Simple Man

Not perfect at anything, but quite good at everything through the power of less is more.

```
return {
    name: "A Simple Man",
    numbOfBullets: 7,   /* 9 points */
    shotsPerTurn: 2,    /* 3 points */
    reloadSpeed: 4,     /* 0 points */
    moveSpeed: 3        /* 3 points */
}

```

```
var lastPos = yourMovement[ yourMovement.length - 1 ],
    lastEnemyPos = enemyMovement[ enemyMovement.length - 1 ],
    lastEnemyMove = enemyMovement.length > 1 ?
        ( function () {
            var i = 0,
                currentMove,
                minMove = Infinity;
            while ( i < enemyMovement.length ) {
                currentMove = Math.abs( enemyMovement[ enemyMovement.length - 1 ] - enemyMovement[ enemyMovement.length - 2 ] );
                if ( currentMove < minMove ) { minMove = currentMove; }
                return minMove;
            }
        } )()
        : 1,
    needsToReload = bulletsLeft === 0;

return {
    shots: [ yourMovement.length === 1 ? 12 : lastEnemyPos + lastEnemyMove, lastEnemyPos - lastEnemyMove ],
    move: needsToReload ? lastPos : lastPos + Math.floor( Math.random() * 3 + 1 ) * ( ( Math.random() > 0.5 ) ? -1 : 1 ),
    reload: needsToReload
};

```
> 5 votes

# Answer
```
var bot = {
    name: "testBot",
    numbOfBullets: 7,
    reloadSpeed: 1,
    shotsPerTurn: 1,
    moveSpeed: 2
}
return bot

```

```
var shots = []
var testBot_moveUp = true
if(Math.random() * 3 > 1)
    testBot_moveUp = false
shots.push(Math.floor((Math.random() * 24) + 1))
var move = 0
if (testBot_moveUp)
    move = yourMovement[yourMovement.length - 1] + 2
else
    move = yourMovement[yourMovement.length - 1] - 2
var play = []
play.shots = shots
play.move = move
play.reload = false
return play

```

Test bot, this added as a control test. If anybody loses to this you should be ashamed :). Fixed bot behaviour, copy pasted the wrong test bot(it always stayed on field 12)
> 4 votes

# Answer
```
var bot = {
    name: "Sniper",
    numbOfBullets: 4,   /* 3 points */
    reloadSpeed: 4,     /* 0 points */
    shotsPerTurn: 1,    /* 0 points */
    moveSpeed: 5        /* 12 points */
};
return bot;

```

```
var play = {};
var my_speed = 5;

var gatherStatistics = function(moves) {
    var enemyMoves = [];

    for (var m = 1; m < moves.length; ++m) {
        var diff = moves[m]-moves[m-1];

        var found = false;
        for (var i = 0; i < enemyMoves.length; ++i) {
            if (enemyMoves[i][0] === diff) {
                ++enemyMoves[i][1];
                found = true;
                break;
            }
        }
        if (!found) enemyMoves.push([diff,1]);
    }

    return enemyMoves;
};
var calcOptimalTarget = function(moves, histogram) {
    var enemy_pos = moves[moves.length-1];
    var optimalDiffs = [];
    var optimalScore = 0;

    for (var i = 0; i < histogram.length; ++i) {
        var diff = histogram[i][0];
        var score = histogram[i][1];

        if (score > optimalScore) {
            optimalScore = score;
            optimalDiffs = [diff];
        } else if (score === optimalScore) {
            optimalDiffs.push(diff);
        }
    }

    var chosenDiff = optimalDiffs[Math.floor(Math.random() * optimalDiffs.length)];
    return enemy_pos + chosenDiff;
};

/* Never reload */
play.reloading = false;

/* Run around like a mad man */
var my_pos = yourMovement[yourMovement.length-1];
var rand_sign = 2*Math.floor(2*Math.random())-1;

/* Never run into walls */
if (my_pos <= my_speed+1) {
    rand_sign = 1;
} else if (my_pos >= 24 - my_speed - 1) {
    rand_sign = -1;
}

if (yourMovement.length === 1) { /* Leap out of the way on first move */
    play.move = yourMovement[yourMovement.length-1] + rand_sign*my_speed;
} else {
    play.move = yourMovement[yourMovement.length-1] + rand_sign*((my_speed-1)*Math.floor(2*Math.random()) + 1);
}

/* Shoot all bullets by the end of the game */
var random_shot = (Math.random() > 0.15) ? true : false;

if (enemyMovement[enemyMovement.length-1] === enemyMovement[enemyMovement.length-2]) {
    /* Enemy is standing still; now is our time to STRIKE! */
    play.shots = [ enemyMovement[enemyMovement.length-1] ];
} else if (enemyMovement.length >= 2 && random_shot) {
    /* We take a random shot; best guess by enemies movement */
    var histogram = gatherStatistics(enemyMovement);
    play.shots = [ calcOptimalTarget(enemyMovement, histogram) ];
} else {
    /* No default shooting */
    play.shots = [];
}

return play;

```
> 4 votes

# Answer
```
var bot = {
    name: "Winger",
    numbOfBullets: 7, // 6 points
    reloadSpeed: 4, // 0 points
    shotsPerTurn: 3, // 6 points
    moveSpeed: 2 // 3 points
}
return bot;

```

```
var play = {};
var moveSpeed = 2;

//Guess the enemies speed
var enSpeed = 5; // Assume they are fast on the first turn
var prev = 12;
for(var move in enemyMovement){
    if(Math.abs(move - prev) > enSpeed){
        enSpeed = Math.abs(move - prev);
    }
    prev = move;
}

var move = 12;
if(Math.random() < 0.5){ moveSpeed = 1; }
//Move against the enemies shots
if(yourMovement.length == 0 || enemyShots.length == 0){
    move = 12 + moveSpeed;
}
else if(enemyShots.length == 1){
    if(enemyShots[0] <= 12){
        move = yourMovement[yourMovement.length - 1] - moveSpeed;
    }
    else{
        move = yourMovement[yourMovement.length - 1] + moveSpeed;
    }
}
else{
    var dir = enemyShots[enemyShots.length - 1][0] - yourMovement[yourMovement.length - 1];
    if(dir > 0){
        move = yourMovement[yourMovement.length - 1] + moveSpeed;
    }
    else{
        move = yourMovement[yourMovement.length - 1] - moveSpeed;
    }
}

//reload?
var reload = false;
if(bulletsLeft < 3){
    reload=true;
}

var enemyPos = 12;
if(enemyMovement.length > 0){
    enemyPos = enemyMovement[enemyMovement.length - 1];
}
var shots = [];
if(reload == false){
    //Shoot a spread around the opponent
    shots.push(enemyPos);
    if(enemyPos + enSpeed <= 24){ shots.push(enemyPos + enSpeed);}
    if(enemyPos - enSpeed > 0){ shots.push(enemyPos - enSpeed);}

}

//Correct move
if(move > 24){
    move = 24;
}
if(move < 1){
    move = 1;
}
if(reload && (yourMovement[yourMovement.length - 1] - yourMovement[yourMovement.length - 2]) != 0){
    move = yourMovement[yourMovement.length - 1];
}

play.move = move;
play.reload = reload;
play.shots = shots;

return play;

```

Winger fires a spread that bounds the enemies range. He also kind of runs towards the enemies shots.

Just gonna leave this here to push the reset.
> 3 votes

# Answer
## The Weaver

More concerned with staying alive than killing, he weaves back and forth, increasing his distance every time. Picks a random spot within the enemies proven range to shoot at.

```
var bot = {
    name: "TheWeaver",
    numbOfBullets: 4, // 3 points
    reloadSpeed: 4, // 0 points
    shotsPerTurn: 1, // 0 points
    moveSpeed: 5 // 12 points
}
return bot;

```

```
var play = {};
var moveSpeed = 2;

//Guess the enemies speed
var enSpeed = 1;
var prev = 12;
for(var move in enemyMovement){
    if(Math.abs(move - prev) > enSpeed){
        enSpeed = Math.abs(move - prev);
    }
    prev = move;
}

//Randomly shoot in his range
var enemyPos = 12;
if(enemyMovement.length > 0){
    enemyPos = enemyMovement[enemyMovement.length - 1];
}
var shots = [];

//Shoot somewhere in his range
var distance = Math.random()*enSpeed;
var direction = 1;
if(Math.random() < 0.5){ direction = -1;}
if(enemyPos + enSpeed > 24){ direction = -1;}
if(enemyPos - enSpeed <= 0){ direction = 1;}
shots.push(enemyPos + distance*direction);

var move = 12;

//Start with a dash
if(yourMovement.length == 0){
    move = 12 + moveSpeed - 1;
}
//Quick switch
else if(yourMovement.length == 1){
    move = 11
}
//Wave baby, weave
else{
    var lastPos = yourMovement[yourMovement.length - 1];
    var lastMove = yourMovement[yourMovement.length - 1] - yourMovement[yourMovement.length - 2];
    var distance = Math.abs(lastMove + 1);
    if(distance > moveSpeed) { distance = 0;}
    var direction = lastMove/Math.abs(lastMove)*(-1);
    move = lastPos + distance*direction;
}

//Correct move
if(move > 24){
    move = 24;
}
if(move < 1){
    move = 1;
}

play.move = move;
play.reload = false;
play.shots = shots;

return play;

```
> 3 votes

# Answer
# Alexander Hamilton

If he doesn't win in the first round, will probably die

```
var bot = {
    name: "Hamilton",
    numbOfBullets: 7, // 6 pts
    reloadSpeed: 4, // 0 pts
    shotsPerTurn: 4, // 9 pts
    moveSpeed: 1 // 0pts
}
return bot

```

!

```
var shots = []
var move = yourMovement[yourMovement.length - 1] + 1
var play = []
play.shots = [12,11,10,13,14,9,15,8,16,7,17,6,18]
play.move = move
play.reload = false
return play

```
> 3 votes

# Answer
# Aaron Burr

```
var bot = {
    name: "Burr",
    numbOfBullets: 7, // 6 pts
    reloadSpeed: 4, // 0 pts
    shotsPerTurn: 3, // 6 pts
    moveSpeed: 2 // 3pts
}
return bot

```

!

```
var shots = []
var move = yourMovement[yourMovement.length - 1]
// Dodging dance
switch (yourMovement.length % 4) {
  case 1:
    move += 2
    break;
  case 2:
    move -= 1
    break;
  case 3:
    move -= 2
    break;
  case 0:
    move += 1
    break;
}
var play = []
var elast = enemyMovement[enemyMovement.length - 1]
play.shots = [elast + 1, elast -1, elast]
play.move = move
play.reload = false
return play

```
> 3 votes

# Answer
```
var bot = {
    name: "Random Evader",
    numbOfBullets: 7,
    reloadSpeed: 4,
    shotsPerTurn: 1,
    moveSpeed: 4
}
return bot

```

```
var getSpeed=function(Moves){
    var m = 0;
    for(var i=1;i<Moves.length;i++){
        var d = Math.abs(Moves[i]-Moves[i-1]);
        m = m>d?m:d;
    }
    return m;
}
var validMove=function(moves,speed){
    speed = speed||getSpeed(moves);
    var m;
    do{
        m=moves[moves.length-1]+Math.floor(Math.random()*(speed*2+1)-speed);
    }while(m>25 && m<0);
    return m;
}
var shots = [];
shots.push(validMove(enemyMovement));
var move = validMove(yourMovement,4);
return {
    shots:shots,
    move:move,
    reload:false
};

```
> 2 votes

# Answer
```
var bot = {
    name: "Gun and run",
    numbOfBullets: 4,   /* 3 points */
    reloadSpeed: 4,     /* 0 points */
    shotsPerTurn: 3,    /* 6 points */
    moveSpeed: 3        /* 6 points */
};
return bot;

```

```
var play = {};
play.reload = false;
if (yourShots.length === 1) { /* Opening move */
    if (Math.random() < 0.5) {
        play.shots = [13,14,15,16];
    } else {
        play.shots = [8,9,10,11];
    }
    play.move = 12;
} else { /* YOLO */
    play.shots = [];
    switch (yourMovement[yourMovement.length - 1]) {
        case 12:
            play.move = 15;
            break;
        case 15:
            play.move = 18;
            break;
        case 18:
            play.move = 15;
            break;
    }
}
return play;

```
> 2 votes

# Answer
# SMG

His gun is his cover. Unfortunately, it seems to block his view. He is also good at taking advantage of standing still to reload faster and get extra shots.

```
var bot = {
    name: "SMG",
    numbOfBullets: 12, //11pt
    reloadSpeed: 2,    //4pt
    shotsPerTurn: 1,   //0pt
    moveSpeed: 1       //0pt
}
return bot

```

```
var shots = [];
shots.push(Math.floor((Math.random() * 24) + 1));
shots.push(Math.floor((Math.random() * 24) + 1));
var play = [];
if (bulletsLeft < 1) {
play.reload = true;
play.shots = [];
}
play.shots = shots;
play.move = Math.floor((Math.random() * 24) + 1);
play.reload = false;
return play;

```
> 2 votes

# Answer
# Diephobus

```
var bot = {
    name: 'Deiphobus',
    numbOfBullets: 5,
    reloadSpeed: 3,
    shotsPerTurn: 4,
    moveSpeed: 1
};
return bot

```

```
var getSorted = function(list)
{
    var modifiedList = [0,0,0,0,0,0,0,0,0,0,0,0,0];
    modifiedList[0] = list[6];
    modifiedList[1] = list[7];
    modifiedList[2] = list[5];
    modifiedList[3] = list[8];
    modifiedList[4] = list[4];
    modifiedList[5] = list[9];
    modifiedList[6] = list[3];
    modifiedList[7] = list[10];
    modifiedList[8] = list[2];
    modifiedList[9] = list[11];
    modifiedList[10] = list[1];
    modifiedList[11] = list[12];
    modifiedList[12] = list[0];

    var messedUpOrder = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];
    for(var order = 0; order < 13; order++) {
        var currBest = -2;

        for (var i = 0; i < 13; i++) {
            if ((messedUpOrder.indexOf(i) < 0) && (modifiedList[i] > modifiedList[currBest] || currBest<0)) {

                currBest = i;
            }
        }

        messedUpOrder[order] = currBest;
    }

    var toRet = [0,0,0,0,0,0,0,0,0,0,0,0,0];
    toRet[6] = messedUpOrder[0];
    toRet[7] = messedUpOrder[1];
    toRet[5] = messedUpOrder[2];
    toRet[8] = messedUpOrder[3];
    toRet[4] = messedUpOrder[4];
    toRet[9] = messedUpOrder[5];
    toRet[3] = messedUpOrder[6];
    toRet[10] = messedUpOrder[7];
    toRet[2] = messedUpOrder[8];
    toRet[11] = messedUpOrder[9];
    toRet[1] = messedUpOrder[10];
    toRet[12] = messedUpOrder[11];
    toRet[0] = messedUpOrder[12];

    return toRet;
};
var myPos;
if(yourMovement.length>0) {
   myPos  = yourMovement[yourMovement.length - 1];
}
else{
    myPos = 12;
}
var EnemyPos;
var play = {
    shots: [
    ],
    reload: true,
    move: 12
};
if(enemyMovement.length>0) {
    EnemyPos = enemyMovement[enemyMovement.length - 1];
}
else
{
    EnemyPos = 12;
}
if(bulletsLeft<4)
{
    play.reload = true;
}
else
{
    play.reload = false;
    var enemyChanges = [0,0,0,0,0,0,0,0,0,0,0,0,0];
    for(var i = 0; i<enemyMovement.length; i++)
    {
        var enemyChange;
        if(i == 0)
        {
            enemyChange = enemyMovement[i] - 12;
        }
        else
        {
            enemyChange = enemyMovement[i] - enemyMovement[i-1];
        }

        enemyChanges[enemyChange+6] = enemyChanges[enemyChange+6]+1;
    }

    var orderedEnemyChanges = getSorted(enemyChanges);
    var CurrentShot = 0;
    play.shots = [12,12,12,12];
    for(var i = 0; i<orderedEnemyChanges.length && CurrentShot<4; i++)
    {
        var pos = orderedEnemyChanges[i] + EnemyPos - 6;
        if(pos<24 && pos>0)
        {
            play.shots[CurrentShot] = pos;
            CurrentShot ++;
        }
    }
}
if(myPos == 1)
{
    play.move = 2;
}
else if (myPos == 23)
{
    play.move = 22;
}
else
{
    play.move = myPos + (Math.floor((Math.random() * 3)) %3) - 1;
}
return play;

```

Diephobus beleives in mercilessly firing bullets everywhere he thinks his enemy might be, but he's a bit slow.
> 1 votes

# Answer
# ASCIIGunInTheWest

Fires 2 shots a turn, and guesses where the enemy can go based on how fast he moves. Forgive me if there's any errors, I haven't coded much in JavaScript.

```
var bot = {
    name: "ASCIIGunInTheWest",
    numbOfBullets: 4,
    reloadSpeed: 1,
    shotsPerTurn: 2,
    moveSpeed: 2
}
return bot

```

!

```
function main(bulletsLeft, yourShots, enemyShots, yourMovement, enemyMovement) {
    var randnum = function (min, max) { return Math.floor( Math.random() * (max - min + 1) ) + min }
    var getDiff = function (num1, num2) { return Math.abs( (num1 > num2) ? num1-num2 : num2-num1 ) }
    var shots = []
    var enemyMaxMovement = 0
    for (index = 0 index < enemyMovement.length ++index) {
    var moveDiff = getDiff(enemyMovement[index], enemyMovement[index - 1])
        if (index != 0 && moveDiff > enemyMaxMovement) {
           enemyMaxMovement = moveDiff
        }
    }
    var enemyCurrentPosition = enemyMovement[enemyMovement.length - 1]
    var enemyMinMoveRange = enemyCurrentPosition - enemyMaxMovement
    var enemyMaxMoveRange = enemyCurrentPosition + enemyMaxMovement
    shots.push( randnum(enemyMinMoveRange, enemyMaxMoveRange) )
    shots.push( randnum(enemyMinMoveRange, enemyMaxMoveRange) )
    var move = yourMovement[yourMovement.length - 1] + randnum(-2, 2)
    var play = []
    play.shots = shots
    play.move = move
    play.reload = false
    return play
}

```

EDIT: Apparently my bot (just mine) can't be used in the JSFiddle. Does anyone know why this is? I'm using all my points for my gunman, so I don't think I've been disqualified.
> 1 votes

---
Tags: king-of-the-hill, javascript
---