<commit_before>#include "util/bitmap.h"
#include "util/trans-bitmap.h"
#include "character-select.h"

#include <fstream>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <string>
#include <cstring>
#include <vector>
#include <ostream>
#include <sstream>
#include <iostream>

#include "stage.h"

#include "util/init.h"
#include "util/resource.h"
#include "util/funcs.h"
#include "util/file-system.h"
#include "util/timedifference.h"
#include "util/thread.h"
#include "globals.h"
#include "factory/font_render.h"
#include "exceptions/shutdown_exception.h"

#include "menu/menu_option.h"
#include "menu/options.h"

#include "animation.h"
#include "background.h"
#include "character.h"
#include "sound.h"
#include "reader.h"
#include "config.h"
#include "sprite.h"
#include "util.h"
#include "font.h"

#include "ast/all.h"
#include "parser/all.h"

#include "util/loading.h"

#include "util/input/input-manager.h"

#include "exceptions/exception.h"

namespace PaintownUtil = ::Util;

using namespace std;
using namespace Mugen;

static const int DEFAULT_WIDTH = 320;
static const int DEFAULT_HEIGHT = 240;
static const int DEFAULT_SCREEN_X_AXIS = 160;
static const int DEFAULT_SCREEN_Y_AXIS = 0;

static const Filesystem::AbsolutePath fixStageName(const std::string &stage){
    /* FIXME not a good solution to get file
     * jon: why isn't it good?
     */
    std::string ourDefFile = stage;
    Filesystem::AbsolutePath baseDir = Filesystem::find(Filesystem::RelativePath("mugen/stages/"));
    if (ourDefFile.find(".def")==std::string::npos){
	ourDefFile += ".def";
    }
    // Get correct directory
    baseDir = Filesystem::AbsolutePath(Mugen::Util::getFileDir(baseDir.path() + ourDefFile));
    return Mugen::Util::getCorrectFileLocation(baseDir, Filesystem::RelativePath(ourDefFile).getFilename().path());
}

FontHandler::FontHandler():
state(Normal),
font(0),
bank(0),
position(0),
blinkFont(0),
blinkBank(0),
blinkPosition(0),
doneFont(0),
doneBank(0),
donePosition(0),
ticker(0),
blinkTime(10),
blinkState(Normal){
}

FontHandler::~FontHandler(){
}

void FontHandler::act(){
    switch(state){
	case Blink:
	    ticker++;
	    if (ticker == blinkTime){
		ticker = 0;
		if (blinkState == Normal){
		    blinkState = Blink;
		} else if (blinkState == Blink){
		    blinkState = Normal;
		}
	    }
	    break;
	case Normal:
	case Done:
	default:
	    break;
    }
}

void FontHandler::render(const std::string &text, const Bitmap &bmp){
    switch(state){
	default:
	case Normal:
	    font->render(location.x, location.y, position, bank, bmp, text);
	    break;
	case Blink:
	    if (blinkState == Normal){
		font->render(location.x, location.y, position, bank, bmp, text);
	    } else if (blinkState == Blink){
		blinkFont->render(location.x, location.y, blinkPosition, blinkBank, bmp, text);
	    }
	    break;
	case Done:
	    doneFont->render(location.x, location.y, donePosition, doneBank, bmp, text);
	    break;
    }
}

CharacterInfo::CharacterInfo(const Filesystem::AbsolutePath &definitionFile):
definitionFile(definitionFile),
baseDirectory(definitionFile.getDirectory()),
// spriteFile(Util::probeDef(definitionFile, "files", "sprite")),
// name(Util::probeDef(definitionFile, "info", "name")),
// displayName(Util::probeDef(definitionFile, "info", "displayname")),
currentPlayer1Act(1),
currentPlayer2Act(1),
icon(0),
portrait(0),
randomStage(false),
order(1),
referenceCell(0),
character1(0),
character2(0){
    Ast::AstParse parsed(Util::parseDef(definitionFile.path()));

    spriteFile = Filesystem::RelativePath(Util::probeDef(parsed, "files", "sprite"));
    name = Util::probeDef(parsed, "info", "name");
    displayName = Util::probeDef(parsed, "info", "displayname");

    /* Grab the act files, in mugen it's strictly capped at 12 so we'll do the same */
    for (int i = 0; i < 12; ++i){
        stringstream act;
        act << "pal" << i;
        try {
            std::string actFile = Util::probeDef(parsed, "files", act.str());
            actCollection.push_back(Filesystem::RelativePath(actFile));
        } catch (const MugenException &me){
            // Ran its course got what we needed
        }
    }

    if (actCollection.size() == 0){
        throw MugenException("No pal files specified");
    }

    // just a precaution
    // spriteFile = Util::removeSpaces(spriteFile);
    icon = Util::probeSff(baseDirectory.join(spriteFile), 9000, 0, true, baseDirectory.join(actCollection[0]));
    portrait = Util::probeSff(baseDirectory.join(spriteFile), 9000, 1, true, baseDirectory.join(actCollection[0]));
}

CharacterInfo::~CharacterInfo(){
    if (icon){
        delete icon;
    }
    if (portrait){
        delete portrait;
    }
    if (character1){
	delete character1;
    }
    if (character2){
	delete character2;
    }
}

void CharacterInfo::loadPlayer1(){
    if (character1){
	return;
    }
    character1 = new Mugen::Character(definitionFile);
    character1->load(currentPlayer1Act);
}

void CharacterInfo::loadPlayer2(){
    if (character2){
	return;
    }
    character2 = new Mugen::Character(definitionFile);
    character2->load(currentPlayer2Act);
}

void CharacterInfo::setPlayer1Act(int number){
    currentPlayer1Act = number;
}

void CharacterInfo::setPlayer2Act(int number){
    currentPlayer2Act = number;
}

// Stage selector
StageHandler::StageHandler():
currentStage(0),
display(false),
selecting(true),
moveSound(0),
selectSound(0){
    stages.push_back(Filesystem::AbsolutePath()); // "Random"
    stageNames.push_back("Stage: Random");
}

StageHandler::~StageHandler(){
}

void StageHandler::act(){
    font.act();
}

void StageHandler::render(const Bitmap &bmp){
    if (display){
	font.render(stageNames[currentStage],bmp);
    }
}
	
//! Get current selected stage
const Filesystem::AbsolutePath & StageHandler::getStage(){
    // check if random first;
    if (currentStage == 0){
	return getRandomStage();
    }
    return stages[currentStage];
}

//! Get random stage
const Filesystem::AbsolutePath & StageHandler::getRandomStage(){
    return stages[PaintownUtil::rnd(1,stages.size())];
}

//! Set Next Stage
void StageHandler::next(){
    if (!selecting){
	return;
    }
    if (currentStage < stages.size()-1){
	currentStage++;
    } else {
	currentStage = 0;
    }
    if (stages.size() > 1){
        if (moveSound){
            moveSound->play();
        }
    }
}

//! Set Prev Stage
void StageHandler::prev(){
    if (!selecting){
	return;
    }
    if (currentStage > 0){
	currentStage--;
    } else {
	currentStage = stages.size()-1;
    }
    if (stages.size() > 1){
        if (moveSound){
            moveSound->play();
        }
    }
}

void StageHandler::toggleSelecting(){
    selecting = !selecting;
    if (!selecting) {
	font.setState(font.Done);
        if (selectSound){
            selectSound->play();
        }
    }
}

//! Add stage to list
void StageHandler::addStage(const std::string &stage){
    try {
	// *FIXME not a good solution to get file
        Filesystem::AbsolutePath ourDefFile = fixStageName(stage);
        // If stage is already stored, ignore it
        if (std::find(stages.begin(), stages.end(), ourDefFile) == stages.end()){
            stringstream temp;
            temp << "Stage " << stages.size() << ": " << Util::probeDef(ourDefFile, "info", "name");
	    stageNames.push_back(temp.str());
	    stages.push_back(ourDefFile);
        }
    } catch (const MugenException &ex){
	Global::debug(0) << "Problem adding stage. Reason: " << ex.getReason() << endl;
    }
}

// Cell
Cell::Cell(int x, int y):
location(x,y),
background(0),
randomSprite(0),
random(false),
blank(false),
empty(true),
characterScaleX(1),
characterScaleY(1),
flash(0),
cursors(None){
}

Cell::~Cell(){
}

void Cell::act(){
    if (flash){
	flash--;
    }
}

void Cell::randomize(std::vector<CharacterInfo *> &characters){
    if (random){
	unsigned int num = PaintownUtil::rnd(0,characters.size());
        character = characters[num];
    }
}

void Cell::render(const Bitmap & bmp){
    if (!blank){
        background->render(position.x,position.y,bmp);
        if (!empty){
            Mugen::Effects effects;
            effects.scalex = characterScaleX;
            effects.scaley = characterScaleY;
            if (random){
                randomSprite->render(position.x + characterOffset.x, position.y + characterOffset.y, bmp,effects);
            } else {
                character->getIcon()->render(position.x + characterOffset.x, position.y + characterOffset.y, bmp,effects);
            }
        }
        if (flash){
            // Bitmap::drawingMode(Bitmap::MODE_TRANS);
            Bitmap::transBlender( 0, 0, 0, int(25.5 * flash) );
            bmp.translucent().rectangleFill( position.x -1, position.y -1, (position.x -1) + dimensions.x, (position.y - 1) + dimensions.y,Bitmap::makeColor(255,255,255));
            // Bitmap::drawingMode(Bitmap::MODE_SOLID);
        }
    }
}

Grid::Grid():
rows(0),
columns(0),
wrapping(false),
showEmptyBoxes(false),
moveOverEmptyBoxes(false),
cellSpacing(0),
cellBackgroundSprite(0),
cellRandomSprite(0),
cellRandomSwitchTime(0),
randomSwitchTimeTicker(0),
portraitScaleX(1),
portraitScaleY(1),
type(Mugen::Arcade){
}

Grid::~Grid(){
    // Destroy cell map
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    if (cell){
		delete cell;
	    }
	}
    }
}

void Grid::initialize(){
    Mugen::Point currentPosition;
    currentPosition.y = position.y;
    for (int row = 0; row < rows; ++row){
	currentPosition.x = position.x;
	std::vector< Cell *> cellRow;
	for (int column = 0; column < columns; ++column){
	    Cell *cell = new Cell(row,column);
	    cell->setBackground(cellBackgroundSprite);
	    cell->setRandomSprite(cellRandomSprite);
	    cell->setPosition(currentPosition.x,currentPosition.y);
	    cell->setDimensions(cellSize.x,cellSize.y);
	    cell->setCharacterOffset(portraitOffset.x, portraitOffset.y);
	    cell->setCharacterScale(portraitScaleX, portraitScaleY);
            // Set random cell with a default character
            if (cell->isRandom()){
                cell->setCharacter(characters.front());
            }
	    cellRow.push_back(cell);
	    currentPosition.x += cellSize.x + cellSpacing;
	}
	cells.push_back(cellRow);
	currentPosition.y += cellSize.y + cellSpacing;
    }
}

void Grid::act(Cursor & player1Cursor, Cursor & player2Cursor){
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    cell->act();
            if (randomSwitchTimeTicker == cellRandomSwitchTime){
                if (player1Cursor.getState() == Cursor::CharacterSelect){
                    if (player1Cursor.getCurrentCell() == cell && cell->isRandom()){
                        cell->randomize(characters);
                        player1Cursor.playRandomSound();
                    }
                }
                if (player2Cursor.getState() == Cursor::CharacterSelect){
                    if (player2Cursor.getCurrentCell() == cell && cell->isRandom()){
                        cell->randomize(characters);
                        player2Cursor.playRandomSound();
                    }
                }
            }
	}
    }

    if (randomSwitchTimeTicker == cellRandomSwitchTime){
        randomSwitchTimeTicker = 0;
    }
    randomSwitchTimeTicker++;

    stages.getFontHandler().act();
}

void Grid::render(const Bitmap & bmp){
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    if (cell->isEmpty()){
		if (showEmptyBoxes && !cell->isBlank()){
		    cell->render(bmp);
		}
	    } else {
		cell->render(bmp);
	    }
	}
    }
}

void Grid::addBlank(){
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    if (cell->isEmpty()){
                cell->setBlank(true);
                return;
            }
        }
    }
}

void Grid::addCharacter(CharacterInfo *character, bool isRandom){
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    if (cell->isEmpty()){
		if (isRandom){
		    cell->setRandom(true);
                    cell->setCharacter(character);
		    return;
		}
		character->setReferenceCell(cell);
		cell->setCharacter(character);
		characters.push_back(character);
		return;
	    } 
	}
    }
}

void Grid::setCursorPlayer1Start(Cursor &cursor){
    Cell *cell = getCell(player1Start.x,player1Start.y);
    cell->setCursorState(Cell::One);
    cursor.setCurrentCell(cell);
}

void Grid::setCursorPlayer2Start(Cursor &cursor){
    Cell *cell = getCell(player2Start.x,player2Start.y);
    cell->setCursorState(Cell::One);
    cursor.setCurrentCell(cell);
}

void Grid::setCursorStageSelect(Cursor & cursor){
    stages.setDisplay(true);
    cursor.setState(Cursor::StageSelect);
}

void Grid::moveCursor(Cursor & cursor, int Point::* field, int wrap, int direction){
    Mugen::Point current = cursor.getCurrentCell()->getLocation();

    Cell *cell = NULL;
    do{
        current.*field += direction;
        if (current.*field < 0){
            if (wrapping){
                current.*field = wrap - 1;
            } else {
                return;
            }
        } else if (current.*field >= wrap){
            current.*field = 0;
        }

        try {
            cell = getCell(current.x, current.y);
        } catch (const MugenException &me){
            Global::debug(0) << "Could not get a cell at " << current.x << ", " << current.y << endl;
            // Shouldn't happen but you never know lets not continue
            return;
        }
        /* skip through blanks */
    } while (cell && cell->isBlank());
    
    if (cell->isEmpty()){<commit_msg>only wrap if its allowed<commit_after>#include "util/bitmap.h"
#include "util/trans-bitmap.h"
#include "character-select.h"

#include <fstream>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <string>
#include <cstring>
#include <vector>
#include <ostream>
#include <sstream>
#include <iostream>

#include "stage.h"

#include "util/init.h"
#include "util/resource.h"
#include "util/funcs.h"
#include "util/file-system.h"
#include "util/timedifference.h"
#include "util/thread.h"
#include "globals.h"
#include "factory/font_render.h"
#include "exceptions/shutdown_exception.h"

#include "menu/menu_option.h"
#include "menu/options.h"

#include "animation.h"
#include "background.h"
#include "character.h"
#include "sound.h"
#include "reader.h"
#include "config.h"
#include "sprite.h"
#include "util.h"
#include "font.h"

#include "ast/all.h"
#include "parser/all.h"

#include "util/loading.h"

#include "util/input/input-manager.h"

#include "exceptions/exception.h"

namespace PaintownUtil = ::Util;

using namespace std;
using namespace Mugen;

static const int DEFAULT_WIDTH = 320;
static const int DEFAULT_HEIGHT = 240;
static const int DEFAULT_SCREEN_X_AXIS = 160;
static const int DEFAULT_SCREEN_Y_AXIS = 0;

static const Filesystem::AbsolutePath fixStageName(const std::string &stage){
    /* FIXME not a good solution to get file
     * jon: why isn't it good?
     */
    std::string ourDefFile = stage;
    Filesystem::AbsolutePath baseDir = Filesystem::find(Filesystem::RelativePath("mugen/stages/"));
    if (ourDefFile.find(".def")==std::string::npos){
	ourDefFile += ".def";
    }
    // Get correct directory
    baseDir = Filesystem::AbsolutePath(Mugen::Util::getFileDir(baseDir.path() + ourDefFile));
    return Mugen::Util::getCorrectFileLocation(baseDir, Filesystem::RelativePath(ourDefFile).getFilename().path());
}

FontHandler::FontHandler():
state(Normal),
font(0),
bank(0),
position(0),
blinkFont(0),
blinkBank(0),
blinkPosition(0),
doneFont(0),
doneBank(0),
donePosition(0),
ticker(0),
blinkTime(10),
blinkState(Normal){
}

FontHandler::~FontHandler(){
}

void FontHandler::act(){
    switch(state){
	case Blink:
	    ticker++;
	    if (ticker == blinkTime){
		ticker = 0;
		if (blinkState == Normal){
		    blinkState = Blink;
		} else if (blinkState == Blink){
		    blinkState = Normal;
		}
	    }
	    break;
	case Normal:
	case Done:
	default:
	    break;
    }
}

void FontHandler::render(const std::string &text, const Bitmap &bmp){
    switch(state){
	default:
	case Normal:
	    font->render(location.x, location.y, position, bank, bmp, text);
	    break;
	case Blink:
	    if (blinkState == Normal){
		font->render(location.x, location.y, position, bank, bmp, text);
	    } else if (blinkState == Blink){
		blinkFont->render(location.x, location.y, blinkPosition, blinkBank, bmp, text);
	    }
	    break;
	case Done:
	    doneFont->render(location.x, location.y, donePosition, doneBank, bmp, text);
	    break;
    }
}

CharacterInfo::CharacterInfo(const Filesystem::AbsolutePath &definitionFile):
definitionFile(definitionFile),
baseDirectory(definitionFile.getDirectory()),
// spriteFile(Util::probeDef(definitionFile, "files", "sprite")),
// name(Util::probeDef(definitionFile, "info", "name")),
// displayName(Util::probeDef(definitionFile, "info", "displayname")),
currentPlayer1Act(1),
currentPlayer2Act(1),
icon(0),
portrait(0),
randomStage(false),
order(1),
referenceCell(0),
character1(0),
character2(0){
    Ast::AstParse parsed(Util::parseDef(definitionFile.path()));

    spriteFile = Filesystem::RelativePath(Util::probeDef(parsed, "files", "sprite"));
    name = Util::probeDef(parsed, "info", "name");
    displayName = Util::probeDef(parsed, "info", "displayname");

    /* Grab the act files, in mugen it's strictly capped at 12 so we'll do the same */
    for (int i = 0; i < 12; ++i){
        stringstream act;
        act << "pal" << i;
        try {
            std::string actFile = Util::probeDef(parsed, "files", act.str());
            actCollection.push_back(Filesystem::RelativePath(actFile));
        } catch (const MugenException &me){
            // Ran its course got what we needed
        }
    }

    if (actCollection.size() == 0){
        throw MugenException("No pal files specified");
    }

    // just a precaution
    // spriteFile = Util::removeSpaces(spriteFile);
    icon = Util::probeSff(baseDirectory.join(spriteFile), 9000, 0, true, baseDirectory.join(actCollection[0]));
    portrait = Util::probeSff(baseDirectory.join(spriteFile), 9000, 1, true, baseDirectory.join(actCollection[0]));
}

CharacterInfo::~CharacterInfo(){
    if (icon){
        delete icon;
    }
    if (portrait){
        delete portrait;
    }
    if (character1){
	delete character1;
    }
    if (character2){
	delete character2;
    }
}

void CharacterInfo::loadPlayer1(){
    if (character1){
	return;
    }
    character1 = new Mugen::Character(definitionFile);
    character1->load(currentPlayer1Act);
}

void CharacterInfo::loadPlayer2(){
    if (character2){
	return;
    }
    character2 = new Mugen::Character(definitionFile);
    character2->load(currentPlayer2Act);
}

void CharacterInfo::setPlayer1Act(int number){
    currentPlayer1Act = number;
}

void CharacterInfo::setPlayer2Act(int number){
    currentPlayer2Act = number;
}

// Stage selector
StageHandler::StageHandler():
currentStage(0),
display(false),
selecting(true),
moveSound(0),
selectSound(0){
    stages.push_back(Filesystem::AbsolutePath()); // "Random"
    stageNames.push_back("Stage: Random");
}

StageHandler::~StageHandler(){
}

void StageHandler::act(){
    font.act();
}

void StageHandler::render(const Bitmap &bmp){
    if (display){
	font.render(stageNames[currentStage],bmp);
    }
}
	
//! Get current selected stage
const Filesystem::AbsolutePath & StageHandler::getStage(){
    // check if random first;
    if (currentStage == 0){
	return getRandomStage();
    }
    return stages[currentStage];
}

//! Get random stage
const Filesystem::AbsolutePath & StageHandler::getRandomStage(){
    return stages[PaintownUtil::rnd(1,stages.size())];
}

//! Set Next Stage
void StageHandler::next(){
    if (!selecting){
	return;
    }
    if (currentStage < stages.size()-1){
	currentStage++;
    } else {
	currentStage = 0;
    }
    if (stages.size() > 1){
        if (moveSound){
            moveSound->play();
        }
    }
}

//! Set Prev Stage
void StageHandler::prev(){
    if (!selecting){
	return;
    }
    if (currentStage > 0){
	currentStage--;
    } else {
	currentStage = stages.size()-1;
    }
    if (stages.size() > 1){
        if (moveSound){
            moveSound->play();
        }
    }
}

void StageHandler::toggleSelecting(){
    selecting = !selecting;
    if (!selecting) {
	font.setState(font.Done);
        if (selectSound){
            selectSound->play();
        }
    }
}

//! Add stage to list
void StageHandler::addStage(const std::string &stage){
    try {
	// *FIXME not a good solution to get file
        Filesystem::AbsolutePath ourDefFile = fixStageName(stage);
        // If stage is already stored, ignore it
        if (std::find(stages.begin(), stages.end(), ourDefFile) == stages.end()){
            stringstream temp;
            temp << "Stage " << stages.size() << ": " << Util::probeDef(ourDefFile, "info", "name");
	    stageNames.push_back(temp.str());
	    stages.push_back(ourDefFile);
        }
    } catch (const MugenException &ex){
	Global::debug(0) << "Problem adding stage. Reason: " << ex.getReason() << endl;
    }
}

// Cell
Cell::Cell(int x, int y):
location(x,y),
background(0),
randomSprite(0),
random(false),
blank(false),
empty(true),
characterScaleX(1),
characterScaleY(1),
flash(0),
cursors(None){
}

Cell::~Cell(){
}

void Cell::act(){
    if (flash){
	flash--;
    }
}

void Cell::randomize(std::vector<CharacterInfo *> &characters){
    if (random){
	unsigned int num = PaintownUtil::rnd(0,characters.size());
        character = characters[num];
    }
}

void Cell::render(const Bitmap & bmp){
    if (!blank){
        background->render(position.x,position.y,bmp);
        if (!empty){
            Mugen::Effects effects;
            effects.scalex = characterScaleX;
            effects.scaley = characterScaleY;
            if (random){
                randomSprite->render(position.x + characterOffset.x, position.y + characterOffset.y, bmp,effects);
            } else {
                character->getIcon()->render(position.x + characterOffset.x, position.y + characterOffset.y, bmp,effects);
            }
        }
        if (flash){
            // Bitmap::drawingMode(Bitmap::MODE_TRANS);
            Bitmap::transBlender( 0, 0, 0, int(25.5 * flash) );
            bmp.translucent().rectangleFill( position.x -1, position.y -1, (position.x -1) + dimensions.x, (position.y - 1) + dimensions.y,Bitmap::makeColor(255,255,255));
            // Bitmap::drawingMode(Bitmap::MODE_SOLID);
        }
    }
}

Grid::Grid():
rows(0),
columns(0),
wrapping(false),
showEmptyBoxes(false),
moveOverEmptyBoxes(false),
cellSpacing(0),
cellBackgroundSprite(0),
cellRandomSprite(0),
cellRandomSwitchTime(0),
randomSwitchTimeTicker(0),
portraitScaleX(1),
portraitScaleY(1),
type(Mugen::Arcade){
}

Grid::~Grid(){
    // Destroy cell map
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    if (cell){
		delete cell;
	    }
	}
    }
}

void Grid::initialize(){
    Mugen::Point currentPosition;
    currentPosition.y = position.y;
    for (int row = 0; row < rows; ++row){
	currentPosition.x = position.x;
	std::vector< Cell *> cellRow;
	for (int column = 0; column < columns; ++column){
	    Cell *cell = new Cell(row,column);
	    cell->setBackground(cellBackgroundSprite);
	    cell->setRandomSprite(cellRandomSprite);
	    cell->setPosition(currentPosition.x,currentPosition.y);
	    cell->setDimensions(cellSize.x,cellSize.y);
	    cell->setCharacterOffset(portraitOffset.x, portraitOffset.y);
	    cell->setCharacterScale(portraitScaleX, portraitScaleY);
            // Set random cell with a default character
            if (cell->isRandom()){
                cell->setCharacter(characters.front());
            }
	    cellRow.push_back(cell);
	    currentPosition.x += cellSize.x + cellSpacing;
	}
	cells.push_back(cellRow);
	currentPosition.y += cellSize.y + cellSpacing;
    }
}

void Grid::act(Cursor & player1Cursor, Cursor & player2Cursor){
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    cell->act();
            if (randomSwitchTimeTicker == cellRandomSwitchTime){
                if (player1Cursor.getState() == Cursor::CharacterSelect){
                    if (player1Cursor.getCurrentCell() == cell && cell->isRandom()){
                        cell->randomize(characters);
                        player1Cursor.playRandomSound();
                    }
                }
                if (player2Cursor.getState() == Cursor::CharacterSelect){
                    if (player2Cursor.getCurrentCell() == cell && cell->isRandom()){
                        cell->randomize(characters);
                        player2Cursor.playRandomSound();
                    }
                }
            }
	}
    }

    if (randomSwitchTimeTicker == cellRandomSwitchTime){
        randomSwitchTimeTicker = 0;
    }
    randomSwitchTimeTicker++;

    stages.getFontHandler().act();
}

void Grid::render(const Bitmap & bmp){
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    if (cell->isEmpty()){
		if (showEmptyBoxes && !cell->isBlank()){
		    cell->render(bmp);
		}
	    } else {
		cell->render(bmp);
	    }
	}
    }
}

void Grid::addBlank(){
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    if (cell->isEmpty()){
                cell->setBlank(true);
                return;
            }
        }
    }
}

void Grid::addCharacter(CharacterInfo *character, bool isRandom){
    for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i){
	std::vector< Cell *> &row = (*i);
	for (std::vector< Cell *>::iterator column = row.begin(); column != row.end(); ++column){
	    Cell *cell = (*column);
	    if (cell->isEmpty()){
		if (isRandom){
		    cell->setRandom(true);
                    cell->setCharacter(character);
		    return;
		}
		character->setReferenceCell(cell);
		cell->setCharacter(character);
		characters.push_back(character);
		return;
	    } 
	}
    }
}

void Grid::setCursorPlayer1Start(Cursor &cursor){
    Cell *cell = getCell(player1Start.x,player1Start.y);
    cell->setCursorState(Cell::One);
    cursor.setCurrentCell(cell);
}

void Grid::setCursorPlayer2Start(Cursor &cursor){
    Cell *cell = getCell(player2Start.x,player2Start.y);
    cell->setCursorState(Cell::One);
    cursor.setCurrentCell(cell);
}

void Grid::setCursorStageSelect(Cursor & cursor){
    stages.setDisplay(true);
    cursor.setState(Cursor::StageSelect);
}

void Grid::moveCursor(Cursor & cursor, int Point::* field, int wrap, int direction){
    Mugen::Point current = cursor.getCurrentCell()->getLocation();

    Cell *cell = NULL;
    do{
        current.*field += direction;
        if (current.*field < 0){
            if (wrapping){
                current.*field = wrap - 1;
            } else {
                return;
            }
        } else if (current.*field >= wrap){
            if (wrapping){
                current.*field = 0;
            } else {
                return;
            }
        }

        try {
            cell = getCell(current.x, current.y);
        } catch (const MugenException &me){
            Global::debug(0) << "Could not get a cell at " << current.x << ", " << current.y << endl;
            // Shouldn't happen but you never know lets not continue
            return;
        }
        /* skip through blanks */
    } while (cell && cell->isBlank());
    
    if (cell->isEmpty()){
{'fraction_non_alphanumeric': 0.15863502511692362, 'fraction_numerical': 0.009561752988047808, 'mean_word_length': 3.1883343006384215, 'pattern_counts': {'":': 2, '<': 113, '<?xml version=': 0, '>': 139, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4714957', 'n_tokens_mistral': 9436, 'n_tokens_neox': 9124, 'n_words': 1963}