// DescriptionHere - game.cpp
// Created by John Ryland (jryland@xiaofrog.com), 29/10/2017
// Copyright (c) 2017 InvertedLogic
// All rights reserved.
#include <cstdio>
#include <cstdlib>
#include "game.h"
bool createNewGame(Game& a_game, int a_width, int a_height, int a_numTileTypes)
{
bool okay = false;
if (a_width == 0 || a_height == 0 || a_numTileTypes == 0)
okay = createBoard(a_game.m_board, 0, 0);
else
okay = generatePlayableBoard(a_game.m_board, a_width, a_height, a_numTileTypes);
if (okay)
{
printBoard(a_game.m_board);
printf("hasAMatch3 returned %s\n", hasAMatch3(a_game.m_board) ? "true" : "false");
printf("hasMoveAvailable returned %s\n", hasMoveAvailable(a_game.m_board) ? "true" : "false");
a_game.m_time = 0;
a_game.m_score = 0;
updateTiles(a_game);
}
if (!okay || !loadGameDB(a_game.m_gameDB))
return false;
return true;
}
void destroyGame(Game& a_game)
{
destroyBoard(a_game.m_board);
}
bool processInput(Game& a_game, const Input& a_input)
{
int x1 = a_input.startTileX;
int y1 = a_input.startTileY;
int x2 = a_input.endTileX;
int y2 = a_input.endTileY;
return swapTiles(a_game, x1, y1, x2, y2);
}
// normalize the game state
// directly translates the state of the board in to the tiles state so they are synced
void updateTiles(Game& a_game)
{
a_game.m_boardTileMap.clear();
a_game.m_tiles.clear();
int idx = 0;
for (int j = 0; j < a_game.height(); j++) {
for (int i = 0; i < a_game.width(); i++) {
Tile t;
t.type = BoardEvent::None;
t.userInit = false;
t.newX = t.x = i;
t.newY = t.y = j;
t.tileTypeId = a_game.m_board.m_board[idx];
a_game.m_tiles.push_back(t);
a_game.m_boardTileMap.push_back(idx);
idx++;
}
}
}
void addTile(Game& a_game, int idx, int x, int y, int value)
{
BoardEvent added;
added.type = BoardEvent::Added;
added.itemIndex = idx;
added.x = x;
added.y = y;
added.value = value;
added.userInit = false;
a_game.m_board.m_board[y*a_game.width() + x] = value;
a_game.m_events.push_back(added);
}
void removeTile(Game& a_game, int idx, int x, int y)
{
BoardEvent removed;
removed.type = BoardEvent::Removed;
removed.itemIndex = idx;
removed.x = x;
removed.y = y;
removed.value = a_game.m_board.m_board[y*a_game.width() + x];
removed.userInit = false;
a_game.m_events.push_back(removed);
}
void moveTile(Game& a_game, int idx, int x, int y, int x2, int y2)
{
BoardEvent moved;
moved.type = BoardEvent::Moved;
moved.itemIndex = idx;
moved.x = x;
moved.y = y;
moved.newX = x2;
moved.newY = y2;
moved.value = a_game.m_board.m_board[y*a_game.width() + x];
moved.userInit = false;
a_game.m_events.push_back(moved);
}
void swapTile(Game& a_game, int idx, int idx2, int x1, int y1, int x2, int y2)
{
BoardEvent swapped;
swapped.type = BoardEvent::Swapped;
swapped.itemIndex = idx;
swapped.newItemIndex = idx2;
swapped.x = x1;
swapped.y = y1;
swapped.newX = x2;
swapped.newY = y2;
swapped.value = a_game.m_board.m_board[y1*a_game.width() + x1];
swapped.userInit = false;
a_game.m_events.push_back(swapped);
}
void moveTilesDown(Game& a_game, int idx, int x, int y)
{
for (int i = y; i >= 0; i--) {
int idx = i * a_game.width() + x;
moveTile(a_game, idx, x, i, x, i+1);
a_game.m_board.m_board[(i+1)*a_game.width() + x] = a_game.m_board.m_board[i*a_game.width() + x];
}
}
bool swapTiles(Game& a_game, int x1, int y1, int x2, int y2)
{
Board& a_board = a_game.m_board;
int w = a_game.width();
int h = a_game.height();
int newIdx = w*h;
if (!canSwapTiles(a_board, x1, y1, x2, y2))
return false;
// This lets up work out the index in to the canvas items / tile list
// TODO: needs to be used - perhaps the BoardEvent struct needs a field added
// a_game.m_boardTileMap.push_back(idx);
int idx = y1 * w + x1;
int idx2 = y2 * w + x2;
swapTile(a_game, idx, idx2, x1, y1, x2, y2);
//swapTile(a_game, idx, x2, y2, x1, y1);
// Actually swap them
int tmp = a_board.m_board[y1*w + x1];
a_board.m_board[y1*w + x1] = a_board.m_board[y2*w + x2];
a_board.m_board[y2*w + x2] = tmp;
bool hasMatches = true;
while (hasMatches)
{
int x1, y1, x2, y2, x3, y3;
hasMatches = getMatch3(a_board, x1, y1, x2, y2, x3, y3);
if (hasMatches)
{
idx = y1 * w + x1;
removeTile(a_game, idx, x1, y1);
moveTilesDown(a_game, idx, x1, y1-1);
addTile(a_game, newIdx++, x1, 0, rand() % 5);
idx = y2 * w + x2;
removeTile(a_game, idx, x2, y2);
moveTilesDown(a_game, idx, x2, y2-1);
addTile(a_game, newIdx++, x2, 0, rand() % 5);
idx = y3 * w + x3;
removeTile(a_game, idx, x3, y3);
moveTilesDown(a_game, idx, x3, y3-1);
addTile(a_game, newIdx++, x3, 0, rand() % 5);
}
// need to update mapping
}
if (!hasMoveAvailable(a_game.m_board))
{
BoardEvent noMoreMoves;
noMoreMoves.type = BoardEvent::NoMoreMoves;
noMoreMoves.userInit = false;
a_game.m_events.push_back(noMoreMoves);
}
//delete[] remapper;
return true;
}