JSFiddle - React, Tailwind, and code Playground

HTML

<style>
html * { font-family: Consolas, Arial, sans-serif; }
select { width: 100%; margin: 12px 0 0 0; }
button, select, input { font-size: 100%; }
input { text-align: right; }
textarea { font-family: "Courier New", monospace; }
textarea[readonly] { background-color: #eee; width: 100%; }
canvas { margin: 12px 0 0 0; border: 2px solid gray; }

.redWrapper, .blueWrapper { width: 30%; }
.redWrapper { float: left; }
.blueWrapper { float: right; }
.arenaWrapper { width: 40%; display: inline-block; }

.redTeam, .blueTeam, .arena { padding: 12px; }
.arena { text-align: center; }
.redTeam, .blueTeam { border-style: solid; border-width: medium; }
.redTeam { border-color: red; background-color: #fee; }
.blueTeam { border-color: blue; background-color: #eef; }

.redTitle, .blueTitle, .arenaTitle { text-align: center; font-size: 200%; }
.redTitle, .blueTitle { font-weight: bold; }
.redTitle { color: red; }
.blueTitle { color: blue; }

.control { margin: 12px 0 0 0; }

.count { font-size: 75%; margin: 0 0 12px 0; }
.footnotes { font-size: 75%; clear: both; padding: 12px; }
</style>
<div id='loadStatus'>
    Loading entries...
</div>
<div>
    <div class='redWrapper'>
        <div class='redTeam'>
            <div class='redTitle'>
                Red Team
            </div>
            <select id='redSelect' size='20' onchange='changeSelect(true)'>
            </select>
            <div class='count'>
                <span id='redCount'></span> players
            </div>
            Code:
            <br>
            <textarea id='redCode' rows='12' readonly></textarea>
            <br>
            <a id='redLink' href='javascript:;'>
                Answer Link
            </a>
        </div>
    </div>
    
    <div class='arenaWrapper'>
        <div class='arena'>
            <div class='arenaTitle'>
                Battlefield
            </div>
            <canvas id='canvas' width='384' height='384'>
                Your browser does not support the canvas tag.
        ...

JavaScript

var qid = 48353
var dq = [] //user ids of disqualified users

var ctx, moveCounter, showNames, showCircles, debug = false
var battle, redTeam, blueTeam, interval

$(document).ready(function() {
    ctx = $('#canvas')[0].getContext('2d')
    moveCounter = $('#moveCounter')
    showNames = $('#showNames')
    showCircles = $('#showCircles')
    loadEntries()
})

function toggleDebug() {
    debug = $('#debug').is(':checked')
}

function rnd(n) {
    return Math.floor(Math.random() * n)
}

function shuffle(o) { //thanks http://stackoverflow.com/a/6274381
    for(var j, x, i = o.length; i; j = rnd(i), x = o[--i], o[i] = o[j], o[j] = x);
    return o
}

function maskedEval(functionBody, params) //thanks http://stackoverflow.com/a/543820
{
    var mask = {}
    for (i in this)
        mask[i] = undefined
    for (i in params) {
        if (params.hasOwnProperty(i))
            mask[i] = params[i]
    }
    return (new Function('with(this) { ' + functionBody + ';}')).call(mask)
}

function createBattle(redTeam, blueTeam, redMovesFirst, animated) {
    var battle = {}
    battle.width = battle.height = 128 //constant
    battle.totalMoves = 2048 //constant
    battle.radius = 16 //constant
    battle.msgMaxLength = 64 //constant
    battle.timeLimit = 15 //milliseconds, constant
    battle.move = 0
    battle.redToMove = redMovesFirst
    battle.animated = animated
    battle.running = false
    battle.over = false
    
    var i = 0, allPositions = new Array(battle.width * battle.height)
    for (var y = 0; y < battle.height; y++) {
        for (var x = 0; x < battle.width; x++)
            allPositions[i++] = { x: x, y: y }
    }
    
    function getRandPos() {
        var i = rnd(allPositions.length)
        var pos = allPositions[i]
        allPositions.splice(i, 1)
        return pos
    }
        
    battle.redTeam = shuffle(redTeam.slice())
    battle.redMsgs = {}
    battle.redKills = {}
    for(var i = 0; i < battle.redTeam.length; i++) {
        var pos =...