<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Cap-Tal]]></title><description><![CDATA[Cap-Tal]]></description><link>https://cap-tal.com/</link><image><url>https://cap-tal.com/favicon.png</url><title>Cap-Tal</title><link>https://cap-tal.com/</link></image><generator>Ghost 1.23</generator><lastBuildDate>Fri, 03 Apr 2026 14:44:55 GMT</lastBuildDate><atom:link href="https://cap-tal.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Building Better Battleship - Part 1]]></title><description><![CDATA[<div class="kg-card-markdown"><p>One of the great things about working on version 1 of a project is that you can learn from version 0. However, step 0 is still to do the design work.</p>
<p>Let's going to start with a short discussion of the features that we want to keep in mind as</p></div>]]></description><link>https://cap-tal.com/building-better-battleship-part-1/</link><guid isPermaLink="false">5a67e2b461b68d0971a26ad1</guid><category><![CDATA[Questionable-Battleship]]></category><category><![CDATA[Projects]]></category><dc:creator><![CDATA[Wesley Wei]]></dc:creator><pubDate>Sun, 28 Jan 2018 07:21:56 GMT</pubDate><media:content url="https://cap-tal.com/content/images/2018/01/Building-Battleship-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cap-tal.com/content/images/2018/01/Building-Battleship-1.png" alt="Building Better Battleship - Part 1"><p>One of the great things about working on version 1 of a project is that you can learn from version 0. However, step 0 is still to do the design work.</p>
<p>Let's going to start with a short discussion of the features that we want to keep in mind as we design, because they will affect a number of design decisions that we make.</p>
<h2 id="keyfeatures">Key Features</h2>
<p>We'll keep our discussion fairly high level here, but we can get into more detail as we get closer to writing code.</p>
<ul>
<li>Battleship Gameplay</li>
<li>Game Modes / Rule Tweaks</li>
<li>Spectators / Replays</li>
<li>Chat</li>
<li>Quick Play / Invite Links</li>
<li>User Accounts</li>
</ul>
<h3 id="battleshipgameplay">Battleship Gameplay</h3>
<p>Rather obviously, the goal is for people to be able to play Battleship. We use the standard rules<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>, so games have two players, players have two boards and 5 ships, gameplay bounces from player to player, etc.</p>
<h3 id="gamemodesruletweaks">Game Modes / Rule Tweaks</h3>
<p>There exists a variation of Battleship in which players fire salvos instead of single shots. We want to be able to accomodate this rule tweak and potentially other rule tweaks in the future, so we need to abstract somewhat over the rules of the game.</p>
<h3 id="spectatorsreplays">Spectators / Replays</h3>
<p>In real life, people can crowd around the physical game and watch the battle unfold. The internet-enabled analog to that is spectators. This requires a log of all game events in a form that can be used to replay events up to arbitrary game state.</p>
<h3 id="chat">Chat</h3>
<p>While we don't need to embed a full featured chat client, being able to echange messages with your opponents without any other setup is something that we think will likely make the Questionable Battleship experience nicer as a whole.</p>
<h3 id="quickplayinvitelinks">Quick Play / Invite Links</h3>
<p>The ability to hit the ground running and just pull up to a game and <em>play</em> is invaluable. Anything we do to streamline that process is a step in the right direction, and this should help. We want Quick Play to be a way for anyone to quickly drop into a game, and we want people to be able to use invite links to quickly join games without any fuss.</p>
<p>It might be possible to extend this concept to queueing to play against another random player or a computer player.</p>
<h3 id="useraccounts">User Accounts</h3>
<p>No one asked for them, but User Accounts make it easier to organize and present potential features down the line.</p>
<p><img src="https://cap-tal.com/content/images/2018/01/Ship-On-Sea.png" alt="Building Better Battleship - Part 1"></p>
<h1 id="designingthebackendserver">Designing the backend server</h1>
<p>The ultimate goal is to play Battleship, so our primary focus is going to be on the representation and manipulation of game state. The other features we discussed may help guide some of our decisions, but they aren't our end goal. So there are at least three things we have to do:</p>
<ol>
<li>Represent game state</li>
<li>Store game state</li>
<li>Represent <em>server</em> state</li>
</ol>
<p>We're fortunate enough here to have Version 0 to interrogate. We can learn quite a bit about how many design decisions panned out as the project progressed. In our discussions of how we plan to accomplish these goals, we'll occasionally look in the direction of the original Questionable Battleship server and what it has to teach us.</p>
<p>Today we'll talk about representing game state.</p>
<h2 id="representinggamestate">Representing Game State</h2>
<p>Games of Battleship seem fairly simple, so we don't expect to have some gargantuan and excessively complicated game state. We don't have quests like Skyrim or consequences to choices like in some RPGs, and we certainly don't have to deal with the open-world that games like Minecraft have to.</p>
<p>We'll start at the top level and work our way down, noting our assumptions as we catch them. We'll almost certainly have to come back later, but but most of the things we have to add or tweak later should have little to do with the completeness our coverage of the state of the game.</p>
<pre><code>Game :: (
    player_1,
    player_2
)
</code></pre>
<blockquote>
<p>Games have two players</p>
</blockquote>
<p>We can all imagine how N-way Battleship might get interesting, especially when Game Modes come into play, but we'll leave that for another day. For now, we'll design with more vanilla tweaks in mind.</p>
<p>Unlike other boards games like Monopoly or Risk, Battleship does not have a shared playing field. Instead, players each have a play area upon which ships are placed and a tracking area.</p>
<pre><code>Game :: (
    player_1,
    player_2,
    board_1,
    board_2,
    tracking_1,
    tracking_2,
    ship_...,
    ....
)
</code></pre>
<blockquote>
<p>Players each have a single play area (Board) and a single tracking area (Tracking)</p>
</blockquote>
<p>We could probably make this flat representation work, but it seems like more trouble than it's worth. Recall that one of our goals is to be able to tweak the way the game works, and this suddenly seems like a terrible idea: Even the smallest change may require that <em>everything else</em> change as well.</p>
<p>Let's break things down a bit then:</p>
<pre><code>Game :: (
    player_1 :: Player,
    player_2 :: Player
)

Player :: (
    board :: Board,
    tracking :: Tracking,
)

Board :: (
    ships :: [Ship]
)
</code></pre>
<p>This is still incomplete, but it's far easier to understand. Games have two players, players have a board and something for tracking, and boards have ships. This also neatly captures ownership relationships, and it'll hopefully help us limit the scope of any tweaks we may have to make.</p>
<p>We still don't know what <code>Tracking</code> is. From a game perspective, it's the tracking grid that players use to track the results of the shots that they've made. In that case, there's relatively little to it: Where a shot was, and what the result was.</p>
<pre><code>Tracking :: (
    shots :: [ Shot ]
)

Result = Hit | Miss | Sink Ship

Shot :: (
    x :: Int,
    y :: Int,
    result :: Result
)
</code></pre>
<blockquote>
<p>Players play on discrete two-dimensional boards</p>
</blockquote>
<blockquote>
<p>Tracking only displays shot results</p>
</blockquote>
<blockquote>
<p>Shots either hit a ship, miss all ships, or sink a ship</p>
</blockquote>
<p>There's room here to add more things to <code>Tracking</code>, but the general spirit is to record the shots that a player has made at their opponent's ships.</p>
<p>So let's talk about <code>Board</code>s and <code>Ship</code>s.</p>
<p>In standard Battleship, boards are squares with 10 cells on each side for a total of 100 cells. Five ships are placed onto each player's board, and they may not intersect.</p>
<p>A ship's position can be described completely by a starting location, a length, and a direction.</p>
<pre><code>Board :: (
    ships :: [ Ship ]
)

Direction = Up | Right | Down | Left

Ship :: (
    x :: Int,
    y :: Int,
    length :: Int,
    direction :: Direction
)
</code></pre>
<blockquote>
<p>Ships can neither intersect nor extend beyond the boundaries of the board.</p>
</blockquote>
<p>Shots fired by the opposing player will either hit a ship or miss all ships. These shots and their results are part of the state of the game, and must be recorded. While it's possible for us to simply keep a complete game log that we can use to replay the game to any point and determine the current state in that fashion, that doesn't feel like an optimal solution.</p>
<p>One way to think about the problem is to note that shots in standard Battleship are unordered: There is no distinction between shooting cell A4 and then cell G6, and shooting cell G6 and then cell A4. Therefore, as long as our chosen strategy allows us to reconstruct the end result of all shots taken, it is acceptable.</p>
<p>We can additionally extend the concept of ownership to shots, or rather their results: recording the shots that hit is the responsibility of the victim. For classic Battleship, that means that ships track the shots that hit them, and the board tracks the shots that miss the ships, or alternatively, the shots that hit the board.</p>
<p>Because the positions of all ships relative to the board is simple to calculate, it is sufficient for ships to record shot positions relative to themselves.</p>
<pre><code>Board :: (
    ships :: [ Ship ],
    misses :: [ Shot ]
)

Direction = Up | Right | Down | Left

Ship :: (
    x :: Int,
    y :: Int,
    length :: Int,
    direction :: Direction,
    hits :: [ Int ]
)

Result = Hit | Miss | Sink Ship

Shot :: (
    x :: Int,
    y :: Int,
    result :: Result
)
</code></pre>
<blockquote>
<p>Shots that missed all ships and shots that hit a ship form a disjoint partition of all shots fired upon a board.</p>
</blockquote>
<p><img src="https://cap-tal.com/content/images/2018/01/Ship-On-Sea.png" alt="Building Better Battleship - Part 1"></p>
<p>Putting everything together, our representation of Battleship state is as follows:</p>
<pre><code>Game :: (
    player_1 :: Player,
    player_2 :: Player
)

Player :: (
    board :: Board,
    tracking :: Tracking,
)

Board :: (
    ships :: [ Ship ],
    misses :: [ Shot ]
)

Direction = Up | Right | Down | Left

Ship :: (
    x :: Int,
    y :: Int,
    length :: Int,
    direction :: Direction,
    hits :: [ Int ]
)

Result = Hit | Miss | Sink Ship

Shot :: (
    x :: Int,
    y :: Int,
    result :: Result
)

Tracking :: (
    shots :: [ Shot ]
)
</code></pre>
<p>I've proposed something slightly shady here: <code>hits :: [ Int ]</code> from <code>Ship</code>. It is the responsibility of ships to record shots that hit them, and there are a few approaches we can take:</p>
<ul>
<li>Keep a list of all ship segments that have been hit</li>
<li>Keep a list of all ship segments that have <em>not</em> been hit</li>
<li>Keep a list of the state of every ship segment</li>
</ul>
<p>I don't yet see any particularly compelling reasons to rule out any of these representations, but if we recall that ships &quot;own&quot; shots in our model, it makes some sense to keep a list of ship segments that have been hit. So for now, we will represent the state of the ship as a list of unique indices, representing the segments that have been hit. This representation makes it easy to tell when a ship sinks: when all of a ship's segments have been hit, it sinks.</p>
<p>I see a little bit of redundancy here:</p>
<pre><code>Board :: (
    ships :: [ Ship ],
    misses :: [ Shot ]
)

Result = Hit | Miss | Sink Ship

Shot :: (
    x :: Int,
    y :: Int,
    result :: Result
)
</code></pre>
<p>We already know that all of the shots recorded by the <code>Board</code> are misses, so we don't need the <code>result</code> field of <code>Shot</code>s.</p>
<pre><code>Board :: (
    ships :: [ Ship ],
    misses :: [ (x :: Int, y :: Int) ]
)
</code></pre>
<p>This works, but makes my skin crawl a little. Coordinate pairs are great, but they aren't treated like pairs anywhere, really. Let's fix that by adding the appropriate data abstraction:</p>
<pre><code>Point :: (
    x :: Int,
    y :: Int
)
</code></pre>
<p>Then our representation becomes:</p>
<pre><code>Game :: (
    player_1 :: Player,
    player_2 :: Player
)

Player :: (
    board :: Board,
    tracking :: Tracking,
)

Point :: (
    x :: Int,
    y :: Int
)

Board :: (
    ships :: [ Ship ],
    misses :: [ Point ]
)

Direction = Up | Right | Down | Left

Ship :: (
    location :: Point,
    length :: Int,
    direction :: Direction,
    hits :: [ Int ]
)

Result = Hit | Miss | Sink Ship

Shot :: (
    location :: Point,
    result :: Result
)

Tracking :: (
    shots :: [ Shot ]
)
</code></pre>
<p>We can revisit this in the future when necessary, but this looks like something we can work with.</p>
<p><img src="https://cap-tal.com/content/images/2018/01/Ship-On-Sea.png" alt="Building Better Battleship - Part 1"></p>
<p><strong>Let's take a moment to talk about strategies for representing board state.</strong></p>
<p>From a programming perspective, it's fairly natural to think of a board as a two-dimensional array. It makes sense to model a two-dimensional grid of cells in the real world with a two-dimensional grid of cells in a program. This approach has the added benefit of being easy to think about and easy to implement. It also tends to perform well, because array lookups are <em>fast</em>. However, when we're doing small lookups in response to player actions, we're unlikely to notice the speed difference unless the server is under heavy load.</p>
<p>The original Questionable Battleship doesn't do this, but the singleplayer proof of concept (PoC) that came before it did. State was represented in a <em>cell-oriented</em> fashion: It concerned itself with the owner of each and every cell on the board, and used those relationships to delegate handling shots. While this seems somewhat elegant, it does lead to a couple of questions with unsatisfying answers.</p>
<ol>
<li><strong>Who owns empty cells?</strong> <br> In a standard game of Battleship, 83 of the 100 cells on each board are unowned. It's not a good idea to delegate the shot to no one, because then the player never gets feedback about their shot. The PoC solved this problem by assigning every unowned cell to a special type of ship: <code>Open Sea</code>. An <code>Open Sea</code> ship is one cell long and always reported that the shot missed. This feels like a bit of a hack, as it abuses the representation to provide &quot;correct&quot; behavior.</li>
<li><strong>How much of this space do we actually need?</strong> <br> In standard Battleship, there are only 17 cells taken up by ships. Further, most games don't end up covering every single cell in artillery shells. It seems like a potential waste of space to unconditionally dole out memory for so many cells that likely won't ever be touched; <em>especially</em> in a server that may have to serve many concurrent games. Simulations run by <a href="http://www.datagenetics.com/blog/december32011/">DataGenetics</a> indicate that if players adhere to a hunt-then-sink strategy, games tend to touch fewer than 70 cells, and players using better strategies will touch even fewer cells! This probably doesn't matter too much in the grand scheme of things, but it leaves a bad taste in my mouth.</li>
</ol>
<p>However, we can think of boards more generally as a set of cells identified by integer coordinates, and there is another way of representing sets: the <a href="https://en.wikipedia.org/wiki/Indicator_function">characteristic function</a>.</p>
<p>In a nutshell, the characteristic function of a set is a way to query membership of an element in a set. A black box, if you will, that answers one question and one question only: &quot;Is this element in the set?&quot;</p>
<p><img src="https://cap-tal.com/content/images/2018/01/Characteristic-fucntion-1.png" alt="Building Better Battleship - Part 1"><br>
<small><br>
Where <code>B</code> is the set being queried<br>
</small></p>
<p>Characteristic functions are interesting to think about. I'm rather partial to the following example, which implements a set.</p>
<p>If you'll allow me to drop into Python for a moment, consider the following:</p>
<pre><code class="language-python">def set():
    def nil(query):
        return false
    return nil

def set_add(set, element):
    def contains(query):
        if query == element:
            return true
        else:
            return set(query)
    return contains

def set_remove(set, element):
    def does_not_contain(query):
        if query == element:
            return false
        else:
            return set(query)
    return does_not_contain
</code></pre>
<br>
<p>A trivial example:</p>
<pre><code class="language-python">s = set()
# s = {}

s = set_add(3)
s = set_add(5)
s = set_add(7)
# s = {3, 5, 7}

if s(2): print(&quot;Set contains 2&quot;) # False
if s(3): print(&quot;Set contains 3&quot;) # True

s = set_remove(3)
# s = {5, 7}

if s(2): print(&quot;Set contains 2&quot;) # False
if s(3): print(&quot;Set contains 3&quot;) # False

</code></pre>
<br>
<p>If you think about it for a little while, you can see why this behaves like a set. It's not exactly computationally efficient, but it works. <code>set()</code> creates an empty set, <code>set_add(element)</code> adds a layer that encodes the presence of <code>element</code> in the set, and <code>set_remove(element)</code> adds a layer that encodes the absence of <code>element</code> in the set! This is a somewhat extreme example, completely foregoing explicit storage in favor of function closures, but it does a marvelous job of getting the point across.</p>
<p>You can see where I'm going with this: We can get away without an actual board in our representation if we keep, in any form, enough data to construct a characteristic function for our boards. This is what the original Questionable Battleship server did, and we plan to stick with that approach.</p>
<p><img src="https://cap-tal.com/content/images/2018/01/Double-Sea.png" alt="Building Better Battleship - Part 1"></p>
<p>That's all I can think of with regards to representing game state for now. We'll leave the discussions of storing game state and representing server state for the future.</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>The Milton Bradley <a href="https://www.hasbro.com/common/instruct/Battleship.PDF">rules for Battleship</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
</div>]]></content:encoded></item><item><title><![CDATA[What is Questionable Battleship?]]></title><description><![CDATA[Questionable, yes. Battleship... technically.]]></description><link>https://cap-tal.com/what-is-questionable-battleship/</link><guid isPermaLink="false">5a642bea61b68d0971a26a68</guid><category><![CDATA[Questionable-Battleship]]></category><category><![CDATA[C.A.Pi.T.A.L.]]></category><dc:creator><![CDATA[Wesley Wei]]></dc:creator><pubDate>Wed, 24 Jan 2018 01:33:14 GMT</pubDate><media:content url="https://cap-tal.com/content/images/2018/01/qb-banner-2.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://cap-tal.com/content/images/2018/01/qb-banner-2.png" alt="What is Questionable Battleship?"><p>Questionable, yes. Battleship... technically.</p>
<p><a href="https://questionablebattleship.com">Questionable Battleship</a> was our first pass at something that people other than ourselves might find interesting, though what we ended up with is a far cry from our original vision. I'll spend a paragraph or three on what you would have seen if you had clicked that link, and the rest I'll devote to a rough sketch of what our ambitions are.</p>
<p><img src="https://cap-tal.com/content/images/2018/01/badship.png" alt="What is Questionable Battleship?"></p>
<p>Currently, we have a very basic implementation of a single version of battleship. We stick fairly closely to what I think is a fairly classic ruleset<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>, though there are some things to watch out for. Two players, the usual ships, single shots in turn, the works. However, since we're indecisive, you may or may not be notified when you sink one of your opponent's ships.</p>
<p>Allow me to clarify: <a href="https://questionablebattleship">This</a> version does not notify you when you sink an opponent's ship, but <a href="https://questionablebattleship.com/simple">this</a> version does.</p>
<p>It'd be great if those were the only differences, but no, that would make it <em>too easy</em> for you to choose which you want to use. In a nutshell, the first version is a fuller experience including sound and some actual graphics, while the latter is a simpler and much more basic experience.</p>
<p><img src="https://cap-tal.com/content/images/2018/01/wonderfulship.png" alt="What is Questionable Battleship?"></p>
<p>Questionable Battleship in its current form doesn't deliver a satisfying experience to players, nor does it have many features that we at C.A.Pi.T.A.L. would like. Below are some ramblings about a few things that we thought might be nice to have.</p>
<h5 id="gamemodes">Game Modes</h5>
<p>There's a variation of Battleship in which players fire off salvos instead of single shots. Then there are further variations on that, changing the number of shots players fire as ships sink. It might also be interesting to see what happens when players' turns advance the game concurrently instead of in alternating order. The upshot is that we'd like to support a somewhat varied set of rules.</p>
<p>Things have the potential to get very strange here very quickly as rules change, but we won't think of everything. So the ultimate goal here is to allow players to mix and match rule tweaks to build somewhat customized game modes on the fly. This is an ambitious endgame goal, for sure, but it's worth working towards.</p>
<h5 id="spectating">Spectating</h5>
<p>When you play a real board game, you're typically right by your opponent, and other people can just walk over and watch the game unfold. However, when you're playing over the internet, you're usually much farther from your opponent and it's much harder for your friends to pop in and watch the game. A spectator feature helps alleviate this [imaginary] problem, but introduces the risk that someone may spectate their own game in an attempt to gain an unfair advantage.</p>
<h5 id="chat">Chat</h5>
<p>Some internet based applications can't be considered complete without some form of chat, but a game like Battleship probably isn't one of them. We don't need too many fancy features like image embedding or a rich text editor, but basic text chat isn't too out of line, nor does it seem too demanding of a task.</p>
<h5 id="quickplayinvitelinks">Quick Play / Invite Links</h5>
<p>Sometimes you just want to play a game of Battleship without worrying about all the other cruft. Even though Questionable Battleship in its current form only asks for a name and a room name, that can still be too much. There should be a way to just drop into a game.</p>
<h5 id="useraccounts">User Accounts</h5>
<p>No one asked for them, and no one really needs an account for a website that just plays Battleship. But we might be able to calculate your overall winrate, and maybe even your winrate against your friends too.</p>
<hr>
<p>That's a rich enough feature list to plan around, and the hope is that it's enough to back up a reasonably polished product that we can release into the wild. It'll keep up busy for a while too though, so keep an eye out for more posts about improving Questionable Battleship!</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://www.hasbro.com/common/instruct/Battleship.PDF">This</a> one should be fairly familiar to most of us <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
</div>]]></content:encoded></item></channel></rss>