I’m in development on a version of Chek for the Pico-8 Fantasy Game Console. Currently, i’m attempting to clear the last bit of Link logic that will allow me to bring it out as Version 1 and start testing and testing and testing some more.

In this article, I’m going to go in-depth on the development of Chek as a digital board game while explicitly speaking to the code and how it works and where I’m at with it. This is in part a discussion on my first real programming project, so please read kindly and know that I don’t know what I’m doing. Or at least, I didn’t much when I started.

First off, Why Pico 8?

I’ve been in love with this platform since I found out about it a couple years ago. It is an extremely accessible engine with graphics, sound and code editors packaged together to make really interesting small games. Not only that but it is incredibly portable with the ability to play it in browser and on mobile, albeit virtual buttons are not the most ideal experience for any console-style game. Additionally, I’ve loaded the platform on a custom-made cartridge that is filled with past game platforms–NES, SEGA etc–and I would love to be able to play my game right alongside those classics. I may even make a small arcade cabinet out of it down the line.

The downside is you do have to hard code everything yourself. It’s based on Lua which has turned out to be a great introductory learning tool for programming, but it has been some work for sure. The environment gives me the immediate ability to test how the code creates and changes the game and that’s where I’m at right now in development.

Most of the game is built. The board, pieces and UI all display properly. I have implemented piece movement as well as detection and attacking. Chain attacks are in place as are Links, but that’s where my final stumbling block lies. While Chains and Links work properly, the logic progresses too quickly. Meaning when a chain attack is executed, it runs fine, but immediately afterward the piece that won the attack will be set to the first cell in the new table of available moves. This means the game moves on its own and improperly.

Blue attacks Red and immediately also takes the 1-6 space instead of staying at 2-7. This is a problem.

That is the final piece of logic to figure out before I implement scoring and win-state… and it has been frustrating.

The Code

Chek code 8-4-18

(notes: “–” and “–[[…]]” indicate commented-out code)

I don’t mind, posting the source code of the game. This version is specifically meant to be shared, and I’ll talk all day long as to how I made it. I’m planning future iterations of the game that will be more fully featured. This is intended to get it out there so people can play it, and I can begin to talk about it more.

Functions

Setup

BSM: the Board State Machine draws the correct color piece or no piece to each cell of the board. This is determined by the value of each cell variable (“red”, “blue”, “yellow”, “green” or nil).

Coord(x): provides coordinates depending on the value of ‘x’ for the Hilight functions to draw.

Highlightall(), Highlightcurrent(), Hilightorig(), Hilightselected(): draws hilight sprites around pieces of interest on board.

Writeback(cell): informs BSM of changes to active cell on board.

Cleanup(): writes previous cell of interest to ‘nil’.

Detects

Test(table,val,dirval): test mother function.

Test_cell(cell): sets status and isblank.

Test_nw(cell), Test_n(cell), Test_ne(cell), Test_e(cell), Test_se(cell), Test_s(cell), Test_sw(cell), Test_w(cell): test each direction to determine if the cell exists on the board.

Cardinal(cell): detect available moves in the N, E, S, W directions. Only adds blank cells and enemy cells to Moves{}.

Radial_bully(cell): detects in all directions whether another piece of the current player’s color surrounds the active cell.

Radial_chainlink(table,cell): detects in all directions available moves. Only adds friendly and enemy cells, no blanks.

Control

Turn_ord(): controls switching between players.

Set_array(): sets cellval to the correct player color index.

Ply_2(): 2-player game setup.

Ply_4(): 4-player game setup.

Chgindex(): button control for selecting possible moves.

Attack

Die(): random die roll.

Atkroll(): sets value of atk.

Defroll(): sets value of def.

Fight_bully(): compares atk v def and adds +1 to atk if bully situation is true; used for initial attack.

Fight_chain(): compares atk v def with constant +1 to atk.

Branching

Choose(): branch control to different game states.

Clprogression(): player progression depending on possibility of chain or link.

Press(): increments pressed. Created to hopefully slow game progression, but not sure needed.

Selectmachine(): btn control depending on game state – newturn, selecting, attacking or chainlinking.

30fps

_Init(): runs a single time to initialize relevant game vars.

_Update(): runs 30x/sec automatically. This is the game, functionally.

_Draw(): draws 30x/sec automatically. using this to draw latent game functions like the board and scoring, title etc.

Important Variables

cellval: player controls this through chgindex() during newturn.

selected: player controls this through chgindex() during other phases.

 

Flow

All color tables are wiped and the BSM writes the state of all current pieces and adds those values to each color table (red{}, blue{}, yellow{}, green{}-referred to as ‘color{}’ here).

Turn_ord() sets the current player and set_array() assigns cellvalI to the first available cell in whichever color{}.

Player cycles through the pieces that are available in color{} (this looks like selecting pieces) and chooses the piece they want to move. Available moves for each piece are highlighted constantly.

Once player selects their desired piece, prv_cell is set to cellval and player begins controlling selected which cycles through the available moveset. Again, all represented in-game.

When the player chooses their move, game evaluates status and isblank to determine if the turn is over or if it’s an enemy cell.

If isblank==true  then writeback() updates the BSM and cleanup() sets prv_cell to nil which also updates the BSM.

If isblank==false then the state is set to attacking and the fight functions run. After the resolution of the attack, the cell is evaluated for either a chain or a link possibility. If none exist than newturn.  If winning player (attacker or defender) can chain attack or link to a brother piece then the chainlinking state is set and the logic runs for attacking or linking as possible. Their is a backout button in this state so player is not caught in a state where they can only link and play stops.

When no chains or links are possible or player backs out newturn is set and play progresses.

 

I have not coded win state or 2/4 player game choice yet. That should be comparatively easy. My main issue at this moment is the logic for play progression. As mentioned earlier, once there is a successful attack, if their is a chain or link possibility, the game is moving too fast and cellval=selected meaning play resumes not at the current, proper spot but at the first value in moves{}. This causes an immediate ‘win’ of that cell where neither player has any choice.