King-Pen! (Dots and Boxes) This is a king of the hill challenge for Dots and Boxes (aka Pen the Pig). The game is simple, on your turn just draw a line on an empty fence. Every time you complete a square you get a point. Also, since we are playing by championship rules, if you complete at least one square on your turn you get an extra turn. This is a round robin tournament, where each bot plays each other bot twice 12 times on a 9x9 grid. Check out this match between two heavyweight titans, where ChainCollector makes mince meat of reigning co-champion Asdf:

Rules

0.5 second time limit per move.
No interfering with other bots.
Use PigPen.random() and PigPen.random(int) for randomness.
No writing to files.
Bot and all its persistent data will be reset every time opponent changes (every 12 rounds).

Bots
Every bot extends Player.java:
package pigpen;

public abstract class Player {

public abstract int[] pick(Board board, int id, int round); 

}

Board is the game board, which mainly serves to give you access to Pen classes, and id is your playerID (tells you if you're first or second), round tells you which round your playing against the same opponent (1 or 2). The return value is an int[], where the first element is the penID (1-indexed), and the second element is the fenceID (0-indexed). See Pen.pick(int) for an easy way to generate this return value. See the Github page for example players and JavaDoc. Since we are only using a square grid ignore any functions and fields related to hexagons.
How to Run

Download Source from Github.
Write your controller bot (make sure to include package pigpen.players) and put it in the src/ folder;
Compile with javac -cp src/* -d . src/*.java. Run with java pigpen.Tournament 4 9 9 false (the last two numbers can be changed to adjust grid size. The last variable should only be set to true if you wish to use the pp_record software.)

Scores

ChainCollector: 72
Asdf: 57
Lazybones: 51
Finisher: 36
=LinearPlayer: 18
=BackwardPlayer: 18
RandomPlayer: 0

See Also:

Dots and Boxes fastest code
Dots and Boxes Wikipedia page

Note: this game is a competitive challenge and not easily solvable, due to giving players an extra turn for completing a box.
Thanks to Nathan Merrill and Darrel Hoffman for consulting on this challenge!
Updates:

Added a moves(int player) method to the Board class to get a list of every move a player has made.


Indefinite Bounty (100 Rep):
First person to post a solution that wins every round, and uses strategy (adjusting play based on observing how the opponent plays).
Lazybones

This bot is lazy. He picks a random spot and direction and continues to build in that direction without moving too much. There are only 2 cases where he does something different:


"make money" by closing a peg with only 1 remaining fence
choose a new spot and direction if placing the fence is not possible or would allow the other bot to "make money"


package pigpen.players;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import pigpen.Board;
import pigpen.Pen;
import pigpen.PigPen;
import pigpen.Player;

public class Lazybones extends Player {
    private static class Fence {
        private static boolean isOk(Board board, boolean vertical, int row, int col) {
            if (vertical) {
                Pen left = board.getPenAt(row, col - 1);
                Pen right = board.getPenAt(row, col);
                if (left.id() &lt; 0 &amp;&amp; right.id() &lt; 0 ||
                        left.fences()[Pen.RIGHT] &gt; 0 ||
                        right.fences()[Pen.LEFT] &gt; 0 ||
                        left.remaining() == 2 ||
                        right.remaining() == 2) {
                    return false;
                }
            } else {
                Pen top = board.getPenAt(row - 1, col);
                Pen bottom = board.getPenAt(row, col);
                if (top.id() &lt; 0 &amp;&amp; bottom.id() &lt; 0 ||
                        top.fences()[Pen.BOTTOM] &gt; 0 ||
                        bottom.fences()[Pen.TOP] &gt; 0 ||
                        top.remaining() == 2 ||
                        bottom.remaining() == 2) {
                    return false;
                }
            }
            return true;
        }

        private static Fence pickRandom(Board board) {
            List&lt;Fence&gt; ok = new ArrayList&lt;&gt;();
            List&lt;Fence&gt; notOk = new ArrayList&lt;&gt;();
            for (int row = 0; row &lt; board.rows; row ++) {
                for (int col = 0; col &lt; board.cols; col ++) {
                    (isOk(board, false, row, col) ? ok : notOk)
                            .add(new Fence(false, row, col));
                    (isOk(board, true, row, col) ? ok : notOk)
                            .add(new Fence(true, row, col));
                }
                (isOk(board, true, row, board.cols) ? ok : notOk)
                        .add(new Fence(true, row, board.cols));
            }
            for (int col = 0; col &lt; board.cols; col ++) {
                (isOk(board, false, board.rows, col) ? ok : notOk)
                        .add(new Fence(false, board.rows, col));
            }
            if (ok.isEmpty()) {
                return notOk.get(PigPen.random(notOk.size()));
            } else {
                return ok.get(PigPen.random(ok.size()));
            }
        }

        private final boolean vertical;
        private final int row;
        private final int col;

        public Fence(boolean vertical, int row, int col) {
            super();
            this.vertical = vertical;
            this.row = row;
            this.col = col;
        }

        private Fence next(Board board, boolean negative) {
            int newRow = vertical ? (negative ? row - 1 : row + 1) : row;
            int newCol = vertical ? col : (negative ? col - 1 : col + 1);
            if (isOk(board, vertical, newRow, newCol)) {
                return new Fence(vertical, newRow, newCol);
            } else {
                return null;
            }
        }

        private int[] getResult(Board board) {
            if (vertical) {
                if (col &lt; board.cols) {
                    return board.getPenAt(row, col).pick(Pen.LEFT);
                } else {
                    return board.getPenAt(row, col - 1).pick(Pen.RIGHT);
                }
            } else {
                if (row &lt; board.rows) {
                    return board.getPenAt(row, col).pick(Pen.TOP);
                } else {
                    return board.getPenAt(row - 1, col).pick(Pen.BOTTOM);
                }
            }
        }
    }

    private Fence lastFence = null;
    private boolean negative = false;

    @Override
    public int[] pick(Board board, int id, int round) {
        List&lt;Pen&gt; money = board.getList().stream()
                .filter(p -&gt; p.remaining() == 1).collect(Collectors.toList());
        if (!money.isEmpty()) {
            return money.get(PigPen.random(money.size())).pick(Pen.TOP);
        }
        if (lastFence != null) {
            lastFence = lastFence.next(board, negative);
        }
        if (lastFence == null) {
            lastFence = Fence.pickRandom(board);
            negative = PigPen.random(2) == 0;
        }
        return lastFence.getResult(board);
    }
}