Exit Full View

Games Cupboard / gamescupboard-server / src / main / kotlin / uk / co / nickthecoder / gamescupboard / server / games / Super7.kt

package uk.co.nickthecoder.gamescupboard.server.games

import uk.co.nickthecoder.gamescupboard.common.*
import uk.co.nickthecoder.gamescupboard.server.*
import uk.co.nickthecoder.gamescupboard.server.commands.RollDiceCommand


private const val right = 720
private const val bottom = playingAreaHeight - 50
private const val top = playingAreaHeight / 2 - 70
private const val boardX = 300
private const val boardY = 300
private const val gridSize = 60

private val redP = SpecialPoint("redCounters", right - 90, bottom)
private val blueP = SpecialPoint("redCounters", right - 90, top)
private val redMegaP = SpecialPoint("redCounters", right - 30, bottom - 120)
private val blueMegaP = SpecialPoint("redCounters", right - 30, top - 120)

private val boardArea = SpecialArea(
    "boardArea", AreaType.PUBLIC,
    boardX - gridSize * 9 / 2,
    boardY - gridSize * 9 / 2,
    gridSize * 9,
    gridSize * 9,
    RectangularSnapToGrid(gridSize, gridSize)
)

private val diceGrid = Grid("dice", "dice.png", 6, 1, 60, 58)

private fun dice(count: Int, x: Int, y: Int, startId: Int, name: String = "dice"): List<GameObject> {
    val result = mutableListOf<GameObject>()
    val spacing = 6
    val totalWidth = count * diceGrid.itemWidth + (count - 1) * spacing
    for (i in 0 until count) {
        result.add(
            MultipleGridImageObject(
                startId + i,
                x - totalWidth / 2 + i * (diceGrid.itemWidth + spacing),
                y,
                name = "$name$i",
                draggable = false,
                grid = diceGrid, fromGX = 0, toGX = 6, fromGY = 0, toGY = 0
            )
        )
    }
    return result
}

val normalSuper7Variation = GameVariation(
    "super7",
    "Super 7",
    minPlayers = 2,
    maxPlayers = 2,

    grids = listOf(diceGrid),

    backgroundObjects = listOf(
        ImageObject(-1, 400, 300, path = "backgrounds/khaki.jpg", draggable = false),
        ImageObject(-2, boardX, boardY, path = "super7Board.png", draggable = false)
    ),

    playingObjects = listOf(
        ImageObject(0, redP.x, redP.y, path = "super7Red.png").apply { regen = true },
        ImageObject(1, redP.x, redP.y, path = "super7Red.png").apply { regen = true },

        ImageObject(2, blueP.x, blueP.y, path = "super7Blue.png").apply { regen = true },
        ImageObject(3, blueP.x, blueP.y, path = "super7Blue.png").apply { regen = true },

        ImageObject(4, redMegaP.x, redMegaP.y, path = "super7RedMega.png").apply { regen = true },
        ImageObject(5, redMegaP.x, redMegaP.y, path = "super7RedMega.png").apply { regen = true },

        ImageObject(6, blueMegaP.x, blueMegaP.y, path = "super7BlueMega.png").apply { regen = true },
        ImageObject(7, blueMegaP.x, blueMegaP.y, path = "super7BlueMega.png").apply { regen = true }
    ) + dice(2, right, 300, startId = 8),

    specialAreas = listOf(boardArea),

    specialPoints = listOf(redP, blueP, redMegaP, blueMegaP),

    avatarPositions = FixedAvatarPositions(
        listOf(
            Vector2i(right, bottom),
            Vector2i(right, top)
        )
    ),

    commands = listOf(RollDiceCommand("dice", 2)),

    commandPrototypes = listOf(
        CommandPrototype(
            "Roll Dice", "roll", isComplete = true, objectNames = listOf("dice0", "dice1")
        )
    ),

    rules = """
        _Super Seven_ is a two player game, similar to `Noughts and Crosses` (aka `Tik-Tak-Toe`),
        but is much more fun, has more strategy, and also some luck.

        The board is made up of 9 `boxes`, and in each `box` there are 9 `squares`.
        Each of the `boxes` is labelled `3` to `11` (large grey text).
        The `squares` are labelled `3` to `11` (small black text),
        with the exception of the each middle `square`, in place of a `7`, there is an asterisk `*`.

        The board is initially empty. The first player (blue), throws a pair of dice.
        The sum of the two dice determines where the player is allowed to place their counter.
        
        _Valid Moves_

        If the player rolls `7`, then they may place their counter in any unoccupied center `squares`
        (the ones with an asterisk `*`).
        Alternatively, they may place their counter in any unoccupied square in the center `box` (the `7` box).
        
        If the player rolls `3` to `6`, or `8` to `11`, the player may place their counter into any unoccupied `square`
        with the corresponding number.
        Alternatively, they may place their counter on a `square` within the `box` with the corresponding number.
        But they may not use a center `square` (with an asterisk `*`).
        
        For example, if the player rolls a `1` and a `2`, (totalling `3`), they may place their piece into any `square`
        numbered `3` ( in the top left of each `box`). Alternatively they may place their counter into `square`
        `3, 4, 5, 6, 8, 9, 10` or `11` of the top left most `box` (the `3` box).

        If the player rolls `2`, they may place their counter on `any` unoccupied `square`.
        
        If the player rolls `12`, they may remove any of their opponents counters, and replace it with their own.

        _Passes_

        If the player cannot move, then they may throw the dice again.
        If they still cannot move, they may throw the dice once more.
        However, if after `three` throws of the dice, they must pass.

        _Aim of the Game_

        The aim of the game is to make lines of three, just as in the game `Noughts and Crosses` (aka `Tik-Tak-Toe`).
        Once a player has a line of three within a `box`, that `box` becomes fully controlled by that player - all 9
        `squares` are filled with the player's counters.
        Neither player may play in this `box` after it has been filled.

        Another way to control a `box` is to place `five` counters of their counters anywhere in the `box`.
        All 9 `squares` are then filled with the player's counters.

        The winner is the first player to get a line of three `boxes`, or control any `5` out of the 9 `boxes`.
        
        _Differences from the Original Game_
        
        When a player controls a `box`, rather than filling the whole `box` with their counters,
        I like to use the `mega` counter.
        The result is the same, but I think the `mega` counters look nicer, and are less fiddly.
        
        """.trimIndent()
)

val super7 = GameType(
    "super7", "Super 7", "super7.png",
    listOf(normalSuper7Variation)
)