<commit_before>//==============================================================================
// Computer engine class
//==============================================================================

#include "computerengine.h"
#include "computerparser.h"

//==============================================================================

#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"

//==============================================================================

#include <QDebug>

//==============================================================================

namespace OpenCOR {
namespace Computer {

//==============================================================================

ComputerEngine::ComputerEngine() :
    mError(QString()),
    mExternalFunctions(ComputerExternalFunctions())
{
    // Create a module

    static int counter = 0;

    mModule = new llvm::Module(QString("Module #%1").arg(QString::number(++counter)).toLatin1().constData(),
                               llvm::getGlobalContext());

    // Initialise the native target, so not only can we then create a JIT
    // execution engine, but more importantly its data layout will match that of
    // our target platform...

    llvm::InitializeNativeTarget();

    // Create a JIT execution engine

    mExecutionEngine = llvm::ExecutionEngine::createJIT(mModule);

    // Create a parser

    mParser = new ComputerParser();
}

//==============================================================================

ComputerEngine::~ComputerEngine()
{
    // Delete some internal objects

    delete mParser;

    delete mExecutionEngine;
    // Note: we must NOT delete mModule, since it gets deleted when deleting
    //       mExecutionEngine...
}

//==============================================================================

llvm::Module * ComputerEngine::module()
{
    // Return the computer engine's module

    return mModule;
}

//==============================================================================

llvm::ExecutionEngine * ComputerEngine::executionEngine()
{
    // Return the computer engine's execution engine

    return mExecutionEngine;
}

//==============================================================================

ComputerError ComputerEngine::error()
{
    // Return the computer engine's error

    return mError;
}

//==============================================================================

ComputerErrors ComputerEngine::parserErrors()
{
    // Return the computer engine's parser's errors

    return mParser->errors();
}

//==============================================================================

llvm::Function * ComputerEngine::addFunction(const QString &pFunction)
{
    qDebug("---------------------------------------");
    qDebug("Compilation of...");
    qDebug();
    qDebug(pFunction.toLatin1().constData());

    // Parse the function

    ComputerFunction function = mParser->parseFunction(pFunction);

    if (function.isValid()) {
        // Output the function's details

        qDebug("---------------------------------------");
        qDebug("Function details:");

        if (function.type() == ComputerFunction::Void)
            qDebug("   Type: void");
        else
            qDebug("   Type: double");

        qDebug(QString("   Name: %1").arg(function.name()).toLatin1().constData());

        qDebug(QString("   Nb of params: %1").arg(QString::number(function.parameters().count())).toLatin1().constData());

        if (!function.parameters().isEmpty())
            foreach (const QString &parameter, function.parameters())
                qDebug(QString("    - %1").arg(parameter).toLatin1().constData());

        if (function.type() == ComputerFunction::Double)
            qDebug(QString("   Return value: %1").arg(function.returnValue()).toLatin1().constData());

        // The function was properly parsed, so check that we don't already
        //  have a function with the same name in our module

        if (mModule->getFunction(function.name().toLatin1().constData())) {
            // A function with the same name already exists, so...

            mError = ComputerError(tr("there is already a function called '%1'").arg(function.name()));

            return 0;
        }

        // No function with the same already exists, so we can try to compile
        // the function

        if (!compileFunction(function))
            // The function couldn't be compiled, so...

            return 0;

        // Return the function's IR code

        return function.irCode();
    } else {
        // The function wasn't properly parsed, so...

        return 0;
    }
}

//==============================================================================

bool ComputerEngine::compileFunction(ComputerFunction &pFunction)
{
    // Generate some LLVM assembly code based on the contents of the function

    static QString indent = QString("  ");
    QString assemblyCode = QString();

    // Declare any external function which we need and in case they are not
    // already declared

    foreach (const ComputerExternalFunction &externalFunction,
             pFunction.externalFunctions())
        if (!mExternalFunctions.contains(externalFunction)) {
            // The function's external function hasn't already been declared, so
            // declare it

            assemblyCode += QString("declare double @%1").arg(externalFunction.name());

            QString parameters = QString();

            for (int i = 0, iMax = externalFunction.nbOfParameters(); i < iMax; ++i) {
                // Add a separator first if we already have 1+ parameters

                if (!parameters.isEmpty())
                    parameters += ", ";

                // Add the parameter definition

                parameters += "double";
            }

            assemblyCode += "("+parameters+") nounwind readnone\n";

            // Add the extenral function to the computer engine's list of
            // external functions

            mExternalFunctions.append(externalFunction);
        }

    if (!assemblyCode.isEmpty())
        assemblyCode += "\n";

    // Define the function

    assemblyCode += "define";

    // Type of function

    if (pFunction.type() == ComputerFunction::Void)
        assemblyCode += " void";
    else
        assemblyCode += " double";

    // Name of the function

    assemblyCode += " @"+pFunction.name();

    // Parameters of the function

    QString parameters = QString();

    foreach (const QString &parameter, pFunction.parameters()) {
        // Add a separator first if we already have 1+ parameters

        if (!parameters.isEmpty())
            parameters += ", ";

        // Add the parameter definition

        parameters += "double* nocapture %%"+parameter;
    }

    assemblyCode += "("+parameters+")";

    // Additional information for the function definition

    assemblyCode += " nounwind uwtable {\n";

    // Mathematical statements

    bool tbaaMetadataNeeded = false;

//---GRY--- TO BE DONE...

    // Return statement

    if (pFunction.type() == ComputerFunction::Void)
        assemblyCode += indent+"ret void\n";
    else
        assemblyCode += indent+"ret double "+pFunction.returnValue()+"\n";

    // End the function

    assemblyCode += "}";

    // Add the TBAA metadata, if neeeded

    if (tbaaMetadataNeeded) {
        assemblyCode += "\n\n";
        assemblyCode += "!0 = metadata !{metadata !\"double\", metadata !1}\n";
        assemblyCode += "!1 = metadata !{metadata !\"omnipotent char\", metadata !2}\n";
        assemblyCode += "!2 = metadata !{metadata !\"Simple C/C++ TBAA\", null}";
    }

    // Now that we are done generating some LLVM assembly code for the function,
    // we can parse that code and have LLVM generate some IR code that will get
    // automatically added to our module

//assemblyCode  = "declare double @sin(double)\n";
//assemblyCode += "\n";
//assemblyCode += "define void @test(double* %%data) {\n";
//assemblyCode += "  %%1 = getelementptr inbounds double* %%data, i64 0\n";
//assemblyCode += "  store double 1.230000e+02, double* %%1, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%2 = getelementptr inbounds double* %%data, i64 2\n";
//assemblyCode += "  store double 1.230000e+02, double* %%2, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%3 = getelementptr inbounds double* %%data, i64 4\n";
//assemblyCode += "  store double 1.230000e+02, double* %%3, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%4 = load double* %%data, align 8\n";
//assemblyCode += "  %%5 = tail call double @sin(double %%4)\n";
//assemblyCode += "  %%6 = getelementptr inbounds double* %%data, i64 1\n";
//assemblyCode += "  store double %%5, double* %%6, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%7 = getelementptr inbounds double* %%data, i64 2\n";
//assemblyCode += "  %%8 = load double* %%7, align 8\n";
//assemblyCode += "  %%9 = tail call double @sin(double %%8) nounwind readnone\n";
//assemblyCode += "  %%10 = getelementptr inbounds double* %%data, i64 3\n";
//assemblyCode += "  store double %%9, double* %%10, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%11 = getelementptr inbounds double* %%data, i64 4\n";
//assemblyCode += "  %%12 = load double* %%11, align 8\n";
//assemblyCode += "  %%13 = tail call double @sin(double %%12) nounwind readnone\n";
//assemblyCode += "  %%14 = getelementptr inbounds double* %%data, i64 5\n";
//assemblyCode += "  store double %%13, double* %%14, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  ret void\n";
//assemblyCode += "}";

    qDebug(QString("   LLVM assembly:\n%1").arg(assemblyCode).toLatin1().constData());

    QString originalAssemblyCode = QString(assemblyCode);
    // Note: the above is required since we must replace '%' with '\%' prior to
    //       having LLVM parse the assembly code, yet we need to keep a trace of
    //       the original assembly code (in case the parsing goes wrong), so...

    llvm::SMDiagnostic parseError;
    llvm::ParseAssemblyString(assemblyCode.replace("%%", "\%").toLatin1().constData(),
                              mModule, parseError, llvm::getGlobalContext());

    if (parseError.getMessage().size())
        mError = ComputerError(tr("the LLVM assembly code could not be parsed: %1").arg(QString::fromStdString(parseError.getMessage()).remove("error: ")),
                               parseError.getLineNo(), parseError.getColumnNo(),
                               originalAssemblyCode);

    // Try to retrieve the function which assembly code we have just parsed

    llvm::Function *function = mModule->getFunction(pFunction.name().toLatin1().constData());

    if (function) {
        // The function could be retrieved, but it should be removed in case an
        // error of sorts occurred during the compilation

        if (!mError.isEmpty()) {
            // An error occurred during the compilation of the function, so...

            function->eraseFromParent();

            return false;
        }

        // Set the function's IR code

        pFunction.setIrCode(function);

        // Everything went fine, so...

        return true;
    } else {
        // The function couldn't be retrieved, so add an error but only if no
        // error occurred during the compilation

        if (mError.isEmpty())
            mError = ComputerError(tr("the function '%1' could not be found").arg(pFunction.name()));

        return false;
    }
}

//==============================================================================

}   // namespace Computer
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Minor editing.<commit_after>//==============================================================================
// Computer engine class
//==============================================================================

#include "computerengine.h"
#include "computerparser.h"

//==============================================================================

#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"

//==============================================================================

#include <QDebug>

//==============================================================================

namespace OpenCOR {
namespace Computer {

//==============================================================================

ComputerEngine::ComputerEngine() :
    mError(QString()),
    mExternalFunctions(ComputerExternalFunctions())
{
    // Create a module

    static int counter = 0;

    mModule = new llvm::Module(QString("Module #%1").arg(QString::number(++counter)).toLatin1().constData(),
                               llvm::getGlobalContext());

    // Initialise the native target, so not only can we then create a JIT
    // execution engine, but more importantly its data layout will match that of
    // our target platform...

    llvm::InitializeNativeTarget();

    // Create a JIT execution engine

    mExecutionEngine = llvm::ExecutionEngine::createJIT(mModule);

    // Create a parser

    mParser = new ComputerParser();
}

//==============================================================================

ComputerEngine::~ComputerEngine()
{
    // Delete some internal objects

    delete mParser;

    delete mExecutionEngine;
    // Note: we must NOT delete mModule, since it gets deleted when deleting
    //       mExecutionEngine...
}

//==============================================================================

llvm::Module * ComputerEngine::module()
{
    // Return the computer engine's module

    return mModule;
}

//==============================================================================

llvm::ExecutionEngine * ComputerEngine::executionEngine()
{
    // Return the computer engine's execution engine

    return mExecutionEngine;
}

//==============================================================================

ComputerError ComputerEngine::error()
{
    // Return the computer engine's error

    return mError;
}

//==============================================================================

ComputerErrors ComputerEngine::parserErrors()
{
    // Return the computer engine's parser's errors

    return mParser->errors();
}

//==============================================================================

llvm::Function * ComputerEngine::addFunction(const QString &pFunction)
{
    qDebug("---------------------------------------");
    qDebug("Compilation of...");
    qDebug();
    qDebug(pFunction.toLatin1().constData());

    // Parse the function

    ComputerFunction function = mParser->parseFunction(pFunction);

    if (function.isValid()) {
        // Output the function's details

        qDebug("---------------------------------------");
        qDebug("Function details:");

        if (function.type() == ComputerFunction::Void)
            qDebug("   Type: void");
        else
            qDebug("   Type: double");

        qDebug(QString("   Name: %1").arg(function.name()).toLatin1().constData());
        qDebug(QString("   Nb of params: %1").arg(QString::number(function.parameters().count())).toLatin1().constData());

        if (!function.parameters().isEmpty())
            foreach (const QString &parameter, function.parameters())
                qDebug(QString("    - %1").arg(parameter).toLatin1().constData());

        if (function.type() == ComputerFunction::Double)
            qDebug(QString("   Return value: %1").arg(function.returnValue()).toLatin1().constData());

        // The function was properly parsed, so check that we don't already have
        // a function with the same name in our module

        if (mModule->getFunction(function.name().toLatin1().constData())) {
            // A function with the same name already exists, so...

            mError = ComputerError(tr("there is already a function called '%1'").arg(function.name()));

            return 0;
        }

        // No function with the same name already exists, so we can try to
        // compile the function

        if (!compileFunction(function))
            // The function couldn't be compiled, so...

            return 0;

        // Return the function's IR code

        return function.irCode();
    } else {
        // The function wasn't properly parsed, so...

        return 0;
    }
}

//==============================================================================

bool ComputerEngine::compileFunction(ComputerFunction &pFunction)
{
    // Generate some LLVM assembly code based on the contents of the function

    static QString indent = QString("  ");
    QString assemblyCode = QString();

    // Declare any external function which we need and which are not already
    // declared

    foreach (const ComputerExternalFunction &externalFunction,
             pFunction.externalFunctions())
        if (!mExternalFunctions.contains(externalFunction)) {
            // The function's external function hasn't already been declared, so
            // declare it

            assemblyCode += QString("declare double @%1").arg(externalFunction.name());

            QString parameters = QString();

            for (int i = 0, iMax = externalFunction.nbOfParameters(); i < iMax; ++i) {
                // Add a separator first if we already have 1+ parameters

                if (!parameters.isEmpty())
                    parameters += ", ";

                // Add the parameter definition

                parameters += "double";
            }

            assemblyCode += "("+parameters+") nounwind readnone\n";

            // Add the extenral function to the computer engine's list of
            // external functions

            mExternalFunctions.append(externalFunction);
        }

    if (!assemblyCode.isEmpty())
        assemblyCode += "\n";

    // Define the function

    assemblyCode += "define";

    // Type of function

    if (pFunction.type() == ComputerFunction::Void)
        assemblyCode += " void";
    else
        assemblyCode += " double";

    // Name of the function

    assemblyCode += " @"+pFunction.name();

    // Parameters of the function

    QString parameters = QString();

    foreach (const QString &parameter, pFunction.parameters()) {
        // Add a separator first if we already have 1+ parameters

        if (!parameters.isEmpty())
            parameters += ", ";

        // Add the parameter definition

        parameters += "double* nocapture %%"+parameter;
    }

    assemblyCode += "("+parameters+")";

    // Additional information for the function definition

    assemblyCode += " nounwind uwtable {\n";

    // Mathematical statements

    bool tbaaMetadataNeeded = false;

//---GRY--- TO BE DONE...

    // Return statement

    if (pFunction.type() == ComputerFunction::Void)
        assemblyCode += indent+"ret void\n";
    else
        assemblyCode += indent+"ret double "+pFunction.returnValue()+"\n";

    // End the function

    assemblyCode += "}";

    // Add the TBAA metadata, if neeeded

    if (tbaaMetadataNeeded) {
        assemblyCode += "\n\n";
        assemblyCode += "!0 = metadata !{metadata !\"double\", metadata !1}\n";
        assemblyCode += "!1 = metadata !{metadata !\"omnipotent char\", metadata !2}\n";
        assemblyCode += "!2 = metadata !{metadata !\"Simple C/C++ TBAA\", null}";
    }

    // Now that we are done generating some LLVM assembly code for the function,
    // we can parse that code and have LLVM generate some IR code that will get
    // automatically added to our module

//assemblyCode  = "declare double @sin(double)\n";
//assemblyCode += "\n";
//assemblyCode += "define void @test(double* %%data) {\n";
//assemblyCode += "  %%1 = getelementptr inbounds double* %%data, i64 0\n";
//assemblyCode += "  store double 1.230000e+02, double* %%1, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%2 = getelementptr inbounds double* %%data, i64 2\n";
//assemblyCode += "  store double 1.230000e+02, double* %%2, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%3 = getelementptr inbounds double* %%data, i64 4\n";
//assemblyCode += "  store double 1.230000e+02, double* %%3, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%4 = load double* %%data, align 8\n";
//assemblyCode += "  %%5 = tail call double @sin(double %%4)\n";
//assemblyCode += "  %%6 = getelementptr inbounds double* %%data, i64 1\n";
//assemblyCode += "  store double %%5, double* %%6, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%7 = getelementptr inbounds double* %%data, i64 2\n";
//assemblyCode += "  %%8 = load double* %%7, align 8\n";
//assemblyCode += "  %%9 = tail call double @sin(double %%8) nounwind readnone\n";
//assemblyCode += "  %%10 = getelementptr inbounds double* %%data, i64 3\n";
//assemblyCode += "  store double %%9, double* %%10, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  %%11 = getelementptr inbounds double* %%data, i64 4\n";
//assemblyCode += "  %%12 = load double* %%11, align 8\n";
//assemblyCode += "  %%13 = tail call double @sin(double %%12) nounwind readnone\n";
//assemblyCode += "  %%14 = getelementptr inbounds double* %%data, i64 5\n";
//assemblyCode += "  store double %%13, double* %%14, align 8\n";
//assemblyCode += "\n";
//assemblyCode += "  ret void\n";
//assemblyCode += "}";

    qDebug(QString("   LLVM assembly:\n%1").arg(assemblyCode).toLatin1().constData());

    QString originalAssemblyCode = QString(assemblyCode);
    // Note: the above is required since we must replace '%' with '\%' prior to
    //       having LLVM parse the assembly code, yet we need to keep a trace of
    //       the original assembly code (in case the parsing goes wrong), so...

    llvm::SMDiagnostic parseError;
    llvm::ParseAssemblyString(assemblyCode.replace("%%", "\%").toLatin1().constData(),
                              mModule, parseError, llvm::getGlobalContext());

    if (parseError.getMessage().size())
        mError = ComputerError(tr("the LLVM assembly code could not be parsed: %1").arg(QString::fromStdString(parseError.getMessage()).remove("error: ")),
                               parseError.getLineNo(), parseError.getColumnNo(),
                               originalAssemblyCode);
        // Note: we must not exit straightaway since LLVM may have generated
        //       some IR code, so we first need to check whether part of the
        //       function has already been generated and, if so, remove it...

    // Try to retrieve the function which assembly code we have just parsed

    llvm::Function *function = mModule->getFunction(pFunction.name().toLatin1().constData());

    if (function) {
        // The function could be retrieved, but it should be removed in case an
        // error of sorts occurred during the parsing of the assembly code

        if (!mError.isEmpty()) {
            // An error occurred during the parsing of the assembly code, so
            // remove the function

            function->eraseFromParent();

            return false;
        }

        // Set the function's IR code

        pFunction.setIrCode(function);

        // Everything went fine, so...

        return true;
    } else {
        // The function couldn't be retrieved, so add an error but only if no
        // error occurred during the parsing of the assembly code

        if (mError.isEmpty())
            mError = ComputerError(tr("the function '%1' could not be found").arg(pFunction.name()));

        return false;
    }
}

//==============================================================================

}   // namespace Computer
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>/**
 * projectM -- Milkdrop-esque visualisation SDK
 * Copyright (C)2003-2004 projectM Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * See 'LICENSE.txt' included within this release
 *
 */

#include <math.h>

#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <chrono>
#include <iostream>

#ifdef WIN32
    #include <shlwapi.h>
    #include <SDL_opengl.h>
    #define DLL_EXPORT __declspec(dllexport)
#else
    #include <SDL2/SDL_opengl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <fstream>
    #define DLL_EXPORT
#endif

#include <projectM.hpp>

#include <sdk/IPcmVisualizer.h>
#include <sdk/IPlugin.h>

#include "Utility.h"
#include "EventMapper.h"

#define MAX_FPS 30LL
#define MILLIS_PER_FRAME (1000LL / MAX_FPS)

#ifndef WIN32
#define COMPILE_AS_EXE
#endif

using namespace std::chrono;

static projectM* pm = nullptr;
static std::atomic<bool> quit(false);
static std::atomic<bool> thread(false);
static std::mutex pcmMutex, threadMutex;
static std::condition_variable threadCondition;

#ifndef WIN32
    static const int MAX_SAMPLES = 1024;
    static const char* PCM_PIPE = "/tmp/musikcube_pcm.pipe";

    static void pipeReadProc() {
        float samples[MAX_SAMPLES];
        int count = 0;

        while (!quit.load()) {
            mkfifo(PCM_PIPE, 0666);
            std::cerr << "pipeReadProc: opening pipe...\n";
            int pipeFd = open(PCM_PIPE, O_RDONLY);
            std::cerr << "pipeReadProc: open returned\n";

            if (pipeFd > 0) {
                std::cerr << "pipeReadProc: pipe stream opened fd=" << pipeFd << "\n";

                bool pipeOpen = true;

                while (pipeFd > 0) {
                    int count = read(pipeFd, (void *)&samples, MAX_SAMPLES * sizeof(float));
                    if (count > 0) {
                        std::unique_lock<std::mutex> lock(pcmMutex);
                        if (pm) {
                            pm->pcm()->addPCMfloat(samples, count / sizeof(float));
                        }
                    }
                    else {
                        close(pipeFd);
                        pipeFd = 0;
                    }
                }
            }
        } /* while (!quit) */

        std::cerr << "pipeReadProc: done\n";
    }
#endif

static void windowProc() {
    SDL_Event event;
    SDL_GLContext glContext = nullptr;
    SDL_Window* screen = nullptr;

    projectMEvent evt;
    projectMKeycode key;
    projectMModifier mod;

    long long start, end;
    bool recreate = true;
    bool fullscreen = false;
    int width = 784;
    int height = 784;
    int flags = 0;
    int x = SDL_WINDOWPOS_UNDEFINED;
    int y = SDL_WINDOWPOS_UNDEFINED;

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        goto cleanup;
    }

    while (!quit.load()) {
        auto start = system_clock::now();

        if (recreate) {
            if (glContext) {
                SDL_GL_DeleteContext(glContext);
            }

            if (screen) {
                SDL_DestroyWindow(screen);
            }

            SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
            SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
            SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

            if (fullscreen) {
                flags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN;
            }
            else {
                flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
            }

            screen = SDL_CreateWindow(
                "projectM", x, y, width, height, flags);

            glContext = SDL_GL_CreateContext(screen);

            if (!pm) {
                std::string configFn = GetProjectMDataDirectory() + "\\config.inp";
                pm = new projectM(configFn);
                pm->projectM_resetGL(width, height);
            }

            recreate = false;
        }

        while (SDL_PollEvent(&event)) {
            evt = sdl2pmEvent(event);
            key = sdl2pmKeycode(event.key.keysym.sym);
            mod = sdl2pmModifier(event.key.keysym.mod);

            if (event.type == SDL_WINDOWEVENT) {
                if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
                    quit.store(true);
                    continue;
                }
            }

            if (evt == PROJECTM_KEYDOWN) {
                if (event.key.keysym.sym == SDLK_SPACE) {
                    /* hack: spacebar locks. */
                    pm->key_handler(evt, PROJECTM_K_l, mod);
                }
                else if (key == PROJECTM_K_f) {
                    if (!fullscreen) {
                        SDL_GetWindowPosition(screen, &x, &y);
                        SDL_GetWindowSize(screen, &width, &height);
                    }

                    fullscreen = !fullscreen;
                    recreate = true;
                }
                else if (key == PROJECTM_K_ESCAPE) {
                    quit.store(true);
                    continue;
                }
                else {
                    pm->key_handler(evt, key, mod);
                }
            }
            else if (evt == PROJECTM_VIDEORESIZE) {
                SDL_GetWindowSize(screen, &width, &height);
                pm->projectM_resetGL(width, height);
                pm->projectM_resetTextures();
            }
        }

        {
            std::unique_lock<std::mutex> lock(pcmMutex);
            pm->renderFrame();
        }

        SDL_GL_SwapWindow(screen);

        auto end = system_clock::now();
        auto delta = duration_cast<milliseconds>(end - start);
        long long waitTime = MILLIS_PER_FRAME - (delta.count());
        if (waitTime > 0) {
            util::sleep(waitTime);
        }
    }

    {
        std::unique_lock<std::mutex> lock(pcmMutex);
        delete pm;
        pm = nullptr;
    }

    SDL_GL_DeleteContext(glContext);
    SDL_DestroyWindow(screen);
    SDL_Quit();

cleanup:
    thread.store(false);

    {
        std::unique_lock<std::mutex> lock(threadMutex);
        threadCondition.notify_all();
    }
}

#ifdef COMPILE_AS_EXE
    int main(int argc, char *argv[]) {
        SetProjectMDataDirectory(util::getModuleDirectory());

#ifndef WIN32
        std::thread background(pipeReadProc);
        background.detach();
#endif

        quit.store(false);
        thread.store(true);
        windowProc();

        return 0;
    }
#else
    #ifdef WIN32
        BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) {
            if (reason == DLL_PROCESS_ATTACH) {
                SetProjectMDataDirectory(util::getModuleDirectory(hModule));
            }
            return true;
        }
    #endif
#endif

#ifdef WIN32
    class Visualizer : public musik::core::audio::IPcmVisualizer {
        public:
            virtual const char* Name() {
                return "projectM IPcmVisualizer";
            };

            virtual const char* Version() {
                return "0.1";
            };

            virtual const char* Author() {
                return "clangen";
            };

            virtual void Destroy() {
                this->Hide();
                delete this;
            }

            virtual void Write(musik::core::audio::IBuffer* buffer) {
                if (Visible()) {
                    std::unique_lock<std::mutex> lock(pcmMutex);
                    if (pm) {
                        pm->pcm()->addPCMfloat(buffer->BufferPointer(), buffer->Samples());
                    }
                }
            }

            virtual void Show() {
                if (!Visible()) {
                    quit.store(false);
                    thread.store(true);
                    std::thread background(windowProc);
                    background.detach();
                }
            }

            virtual void Hide() {
                if (Visible()) {
                    quit.store(true);

                    while (thread.load()) {
                        std::unique_lock<std::mutex> lock(threadMutex);
                        threadCondition.wait(lock);
                    }
                }
            }

            virtual bool Visible() {
                return thread.load();
            }
    };

    extern "C" DLL_EXPORT musik::core::IPlugin* GetPlugin() {
        return new Visualizer();
    }

    extern "C" DLL_EXPORT musik::core::audio::IPcmVisualizer* GetPcmVisualizer() {
        return new Visualizer();
    }
#endif
<commit_msg>Tweaked the Win32 visualizer name to match *Nix<commit_after>/**
 * projectM -- Milkdrop-esque visualisation SDK
 * Copyright (C)2003-2004 projectM Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * See 'LICENSE.txt' included within this release
 *
 */

#include <math.h>

#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <chrono>
#include <iostream>

#ifdef WIN32
    #include <shlwapi.h>
    #include <SDL_opengl.h>
    #define DLL_EXPORT __declspec(dllexport)
#else
    #include <SDL2/SDL_opengl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <fstream>
    #define DLL_EXPORT
#endif

#include <projectM.hpp>

#include <sdk/IPcmVisualizer.h>
#include <sdk/IPlugin.h>

#include "Utility.h"
#include "EventMapper.h"

#define MAX_FPS 30LL
#define MILLIS_PER_FRAME (1000LL / MAX_FPS)

#ifndef WIN32
#define COMPILE_AS_EXE
#endif

using namespace std::chrono;

static projectM* pm = nullptr;
static std::atomic<bool> quit(false);
static std::atomic<bool> thread(false);
static std::mutex pcmMutex, threadMutex;
static std::condition_variable threadCondition;

#ifndef WIN32
    static const int MAX_SAMPLES = 1024;
    static const char* PCM_PIPE = "/tmp/musikcube_pcm.pipe";

    static void pipeReadProc() {
        float samples[MAX_SAMPLES];
        int count = 0;

        while (!quit.load()) {
            mkfifo(PCM_PIPE, 0666);
            std::cerr << "pipeReadProc: opening pipe...\n";
            int pipeFd = open(PCM_PIPE, O_RDONLY);
            std::cerr << "pipeReadProc: open returned\n";

            if (pipeFd > 0) {
                std::cerr << "pipeReadProc: pipe stream opened fd=" << pipeFd << "\n";

                bool pipeOpen = true;

                while (pipeFd > 0) {
                    int count = read(pipeFd, (void *)&samples, MAX_SAMPLES * sizeof(float));
                    if (count > 0) {
                        std::unique_lock<std::mutex> lock(pcmMutex);
                        if (pm) {
                            pm->pcm()->addPCMfloat(samples, count / sizeof(float));
                        }
                    }
                    else {
                        close(pipeFd);
                        pipeFd = 0;
                    }
                }
            }
        } /* while (!quit) */

        std::cerr << "pipeReadProc: done\n";
    }
#endif

static void windowProc() {
    SDL_Event event;
    SDL_GLContext glContext = nullptr;
    SDL_Window* screen = nullptr;

    projectMEvent evt;
    projectMKeycode key;
    projectMModifier mod;

    long long start, end;
    bool recreate = true;
    bool fullscreen = false;
    int width = 784;
    int height = 784;
    int flags = 0;
    int x = SDL_WINDOWPOS_UNDEFINED;
    int y = SDL_WINDOWPOS_UNDEFINED;

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        goto cleanup;
    }

    while (!quit.load()) {
        auto start = system_clock::now();

        if (recreate) {
            if (glContext) {
                SDL_GL_DeleteContext(glContext);
            }

            if (screen) {
                SDL_DestroyWindow(screen);
            }

            SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
            SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
            SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

            if (fullscreen) {
                flags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN;
            }
            else {
                flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
            }

            screen = SDL_CreateWindow(
                "projectM", x, y, width, height, flags);

            glContext = SDL_GL_CreateContext(screen);

            if (!pm) {
                std::string configFn = GetProjectMDataDirectory() + "\\config.inp";
                pm = new projectM(configFn);
                pm->projectM_resetGL(width, height);
            }

            recreate = false;
        }

        while (SDL_PollEvent(&event)) {
            evt = sdl2pmEvent(event);
            key = sdl2pmKeycode(event.key.keysym.sym);
            mod = sdl2pmModifier(event.key.keysym.mod);

            if (event.type == SDL_WINDOWEVENT) {
                if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
                    quit.store(true);
                    continue;
                }
            }

            if (evt == PROJECTM_KEYDOWN) {
                if (event.key.keysym.sym == SDLK_SPACE) {
                    /* hack: spacebar locks. */
                    pm->key_handler(evt, PROJECTM_K_l, mod);
                }
                else if (key == PROJECTM_K_f) {
                    if (!fullscreen) {
                        SDL_GetWindowPosition(screen, &x, &y);
                        SDL_GetWindowSize(screen, &width, &height);
                    }

                    fullscreen = !fullscreen;
                    recreate = true;
                }
                else if (key == PROJECTM_K_ESCAPE) {
                    quit.store(true);
                    continue;
                }
                else {
                    pm->key_handler(evt, key, mod);
                }
            }
            else if (evt == PROJECTM_VIDEORESIZE) {
                SDL_GetWindowSize(screen, &width, &height);
                pm->projectM_resetGL(width, height);
                pm->projectM_resetTextures();
            }
        }

        {
            std::unique_lock<std::mutex> lock(pcmMutex);
            pm->renderFrame();
        }

        SDL_GL_SwapWindow(screen);

        auto end = system_clock::now();
        auto delta = duration_cast<milliseconds>(end - start);
        long long waitTime = MILLIS_PER_FRAME - (delta.count());
        if (waitTime > 0) {
            util::sleep(waitTime);
        }
    }

    {
        std::unique_lock<std::mutex> lock(pcmMutex);
        delete pm;
        pm = nullptr;
    }

    SDL_GL_DeleteContext(glContext);
    SDL_DestroyWindow(screen);
    SDL_Quit();

cleanup:
    thread.store(false);

    {
        std::unique_lock<std::mutex> lock(threadMutex);
        threadCondition.notify_all();
    }
}

#ifdef COMPILE_AS_EXE
    int main(int argc, char *argv[]) {
        SetProjectMDataDirectory(util::getModuleDirectory());

#ifndef WIN32
        std::thread background(pipeReadProc);
        background.detach();
#endif

        quit.store(false);
        thread.store(true);
        windowProc();

        return 0;
    }
#else
    #ifdef WIN32
        BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) {
            if (reason == DLL_PROCESS_ATTACH) {
                SetProjectMDataDirectory(util::getModuleDirectory(hModule));
            }
            return true;
        }
    #endif
#endif

#ifdef WIN32
    class Visualizer : public musik::core::audio::IPcmVisualizer {
        public:
            virtual const char* Name() {
                return "projectM";
            };

            virtual const char* Version() {
                return "0.1";
            };

            virtual const char* Author() {
                return "clangen";
            };

            virtual void Destroy() {
                this->Hide();
                delete this;
            }

            virtual void Write(musik::core::audio::IBuffer* buffer) {
                if (Visible()) {
                    std::unique_lock<std::mutex> lock(pcmMutex);
                    if (pm) {
                        pm->pcm()->addPCMfloat(buffer->BufferPointer(), buffer->Samples());
                    }
                }
            }

            virtual void Show() {
                if (!Visible()) {
                    quit.store(false);
                    thread.store(true);
                    std::thread background(windowProc);
                    background.detach();
                }
            }

            virtual void Hide() {
                if (Visible()) {
                    quit.store(true);

                    while (thread.load()) {
                        std::unique_lock<std::mutex> lock(threadMutex);
                        threadCondition.wait(lock);
                    }
                }
            }

            virtual bool Visible() {
                return thread.load();
            }
    };

    extern "C" DLL_EXPORT musik::core::IPlugin* GetPlugin() {
        return new Visualizer();
    }

    extern "C" DLL_EXPORT musik::core::audio::IPcmVisualizer* GetPcmVisualizer() {
        return new Visualizer();
    }
#endif
<|endoftext|>


<commit_before><commit_msg>remove unnecessary stuff<commit_after><|endoftext|>


<commit_before><commit_msg>Reverting 19447.<commit_after><|endoftext|>


<commit_before><commit_msg>Make function definition order (.cc) match function declaration order (.h).  No code changes.<commit_after><|endoftext|>


<commit_before><commit_msg>Revert thakis's changes to download_file.cc from r17595.<commit_after><|endoftext|>


<commit_before><commit_msg>Fix bookmark util crash<commit_after><|endoftext|>


<commit_before><commit_msg>Show bookmark manager on Linux when menu shortcut is pressed (ctrl-shift-b).<commit_after><|endoftext|>


<commit_before><commit_msg>Add test for history HTML escaping issue.<commit_after><|endoftext|>


<commit_before>#include "stan/math/functions/log_rising_factorial.hpp"
#include <gtest/gtest.h>

TEST(MathFunctions, log_rising_factorial) {
  using stan::math::log_rising_factorial;

  EXPECT_FLOAT_EQ(std::log(120.0), log_rising_factorial(4.0,3));
  EXPECT_FLOAT_EQ(std::log(360.0), log_rising_factorial(3.0,4));
  EXPECT_THROW(log_rising_factorial(-1, 4),std::domain_error);
}
<commit_msg>added NaN test for log_rising_factorial<commit_after>#include <stan/math/functions/log_rising_factorial.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <gtest/gtest.h>

TEST(MathFunctions, log_rising_factorial) {
  using stan::math::log_rising_factorial;

  EXPECT_FLOAT_EQ(std::log(120.0), log_rising_factorial(4.0,3));
  EXPECT_FLOAT_EQ(std::log(360.0), log_rising_factorial(3.0,4));
  EXPECT_THROW(log_rising_factorial(-1, 4),std::domain_error);
}

TEST(MathFunctions, log_rising_factorial_nan) {
  double nan = std::numeric_limits<double>::quiet_NaN();

  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::log_rising_factorial(nan, 3));
}
<|endoftext|>


<commit_before>#include "common.h"
#include "PlayerController.h"
#include "EventManager.h"
#include "PositionComponent.h"
#include "OrientationComponent.h"
#include "BoundingComponent.h"
#include "ModelComponent.h"

void PlayerController::Init() {
	const std::vector<Triangle> triangles = {
		std::make_tuple(Point3(-0.375, -0.85,  0.25), Point3( 0.375, -0.85,  0.25), Point3(-0.375,  0.85,  0.25)),
		std::make_tuple(Point3( 0.375, -0.85,  0.25), Point3( 0.375,  0.85,  0.25), Point3(-0.375,  0.85,  0.25)),
		std::make_tuple(Point3(-0.375,  0.85,  0.25), Point3( 0.375,  0.85,  0.25), Point3(-0.375,  0.85, -0.25)),
		std::make_tuple(Point3( 0.375,  0.85,  0.25), Point3( 0.375,  0.85, -0.25), Point3(-0.375,  0.85, -0.25)),
		std::make_tuple(Point3(-0.375,  0.85, -0.25), Point3( 0.375,  0.85, -0.25), Point3(-0.375, -0.85, -0.25)),
		std::make_tuple(Point3( 0.375,  0.85, -0.25), Point3( 0.375, -0.85, -0.25), Point3(-0.375, -0.85, -0.25)),
		std::make_tuple(Point3(-0.375, -0.85, -0.25), Point3( 0.375, -0.85, -0.25), Point3(-0.375, -0.85,  0.25)),
		std::make_tuple(Point3( 0.375, -0.85, -0.25), Point3( 0.375, -0.85,  0.25), Point3(-0.375, -0.85,  0.25)),
		std::make_tuple(Point3( 0.375, -0.85,  0.25), Point3( 0.375, -0.85, -0.25), Point3( 0.375,  0.85,  0.25)),
		std::make_tuple(Point3( 0.375, -0.85, -0.25), Point3( 0.375,  0.85, -0.25), Point3( 0.375,  0.85,  0.25)),
		std::make_tuple(Point3(-0.375, -0.85, -0.25), Point3(-0.375, -0.85,  0.25), Point3(-0.375,  0.85, -0.25)),
		std::make_tuple(Point3(-0.375, -0.85,  0.25), Point3(-0.375,  0.85,  0.25), Point3(-0.375,  0.85, -0.25))
	};

	object = engine->AddObject();
	engine->AddComponent<PositionComponent>(object);
	engine->AddComponent<OrientationComponent>(object);
	engine->AddComponent<BoundingComponent>(object, Point3(-0.375f, -0.85f, -0.25f), Point3(0.75f, 1.7f, 0.5f));
	engine->AddComponent<ModelComponent>(object, triangles);
	InitObject();

	auto ownPos = engine->GetComponent<PositionComponent>(object);
	auto ownBounds = engine->GetComponent<BoundingComponent>(object);

	/* gravity */
	ownPos->position.Derivative(1) = Point3(0, -9.8f, 0);

	/* collision detection and response */
	engine->systems.Get<EventManager>()->ListenFor("integrator", "ticked", [this, ownPos, ownBounds] (Arg delta) {
		auto &prev = ownPos->position.GetPrevious();
		auto &curr = *ownPos->position;
		auto &vel = *ownPos->position.Derivative();

		Point3 normal;
		float entryTime = 0.0f;

		auto pair = engine->objects.right.equal_range(&typeid(BoundingComponent));

		/* loop until all collisions have been resolved */
		while(entryTime != 1.0f) {
			auto tickVel = vel * delta.float_;
			entryTime = 1.0f;

			/* find collision with soonest entry time */
			for(auto it = pair.first; it != pair.second; ++it) {
				auto id = it->get_left();

				/* don't check for collisions with self */
				if(id == object) { continue; }

				auto objPos = engine->GetComponent<PositionComponent>(id);
				if(objPos != nullptr) {
					auto objBounds = engine->GetComponent<BoundingComponent>(id);
					if(objBounds != nullptr) {
						auto r = ownBounds->box.AABBSwept(objBounds->box, std::make_tuple(prev, curr, tickVel), *objPos->position);
						if(std::get<0>(r) < entryTime) { std::tie(entryTime, normal) = r; }
					}
				}
			}

			/* respond to collision */
			if(entryTime < 1.0f) {
				/* project previous position to point of entry of collision */
				prev += tickVel * entryTime;

				/* project position onto surface by subtracting surface-to-end vector */
				curr -= normal * glm::dot(tickVel, normal);

				/* project velocity onto surface too
				 * y is given a bounce factor of 0.125
				 */
				vel -= normal * glm::dot(Point3(vel.x, vel.y * 1.125f, vel.z), normal);
			}
		}
	});
}

void PlayerController::Update(DeltaTicks &dt) {
	auto ownPos = engine->GetComponent<PositionComponent>(object);
	auto ownOrient = engine->GetComponent<OrientationComponent>(object);

	auto rel = glm::normalize(Point4((moveLeft ? -1 : 0) + (moveRight ? 1 : 0), 0, (moveForward ? -1 : 0) + (moveBackward ? 1 : 0), 1));
	auto abs = (glm::inverse(ownOrient->orientation) * rel) * 4.0f; /* 4 meters per second */

	/* TODO: footstep spread is between 0.5m and 1m */

	ownPos->position.Derivative()->x = abs.x;
	//pos->position.Derivative()->y = abs.y;
	ownPos->position.Derivative()->z = abs.z;
}
<commit_msg>Decrease movement speed slightly<commit_after>#include "common.h"
#include "PlayerController.h"
#include "EventManager.h"
#include "PositionComponent.h"
#include "OrientationComponent.h"
#include "BoundingComponent.h"
#include "ModelComponent.h"

void PlayerController::Init() {
	const std::vector<Triangle> triangles = {
		std::make_tuple(Point3(-0.375, -0.85,  0.25), Point3( 0.375, -0.85,  0.25), Point3(-0.375,  0.85,  0.25)),
		std::make_tuple(Point3( 0.375, -0.85,  0.25), Point3( 0.375,  0.85,  0.25), Point3(-0.375,  0.85,  0.25)),
		std::make_tuple(Point3(-0.375,  0.85,  0.25), Point3( 0.375,  0.85,  0.25), Point3(-0.375,  0.85, -0.25)),
		std::make_tuple(Point3( 0.375,  0.85,  0.25), Point3( 0.375,  0.85, -0.25), Point3(-0.375,  0.85, -0.25)),
		std::make_tuple(Point3(-0.375,  0.85, -0.25), Point3( 0.375,  0.85, -0.25), Point3(-0.375, -0.85, -0.25)),
		std::make_tuple(Point3( 0.375,  0.85, -0.25), Point3( 0.375, -0.85, -0.25), Point3(-0.375, -0.85, -0.25)),
		std::make_tuple(Point3(-0.375, -0.85, -0.25), Point3( 0.375, -0.85, -0.25), Point3(-0.375, -0.85,  0.25)),
		std::make_tuple(Point3( 0.375, -0.85, -0.25), Point3( 0.375, -0.85,  0.25), Point3(-0.375, -0.85,  0.25)),
		std::make_tuple(Point3( 0.375, -0.85,  0.25), Point3( 0.375, -0.85, -0.25), Point3( 0.375,  0.85,  0.25)),
		std::make_tuple(Point3( 0.375, -0.85, -0.25), Point3( 0.375,  0.85, -0.25), Point3( 0.375,  0.85,  0.25)),
		std::make_tuple(Point3(-0.375, -0.85, -0.25), Point3(-0.375, -0.85,  0.25), Point3(-0.375,  0.85, -0.25)),
		std::make_tuple(Point3(-0.375, -0.85,  0.25), Point3(-0.375,  0.85,  0.25), Point3(-0.375,  0.85, -0.25))
	};

	object = engine->AddObject();
	engine->AddComponent<PositionComponent>(object);
	engine->AddComponent<OrientationComponent>(object);
	engine->AddComponent<BoundingComponent>(object, Point3(-0.375f, -0.85f, -0.25f), Point3(0.75f, 1.7f, 0.5f));
	engine->AddComponent<ModelComponent>(object, triangles);
	InitObject();

	auto ownPos = engine->GetComponent<PositionComponent>(object);
	auto ownBounds = engine->GetComponent<BoundingComponent>(object);

	/* gravity */
	ownPos->position.Derivative(1) = Point3(0, -9.8f, 0);

	/* collision detection and response */
	engine->systems.Get<EventManager>()->ListenFor("integrator", "ticked", [this, ownPos, ownBounds] (Arg delta) {
		auto &prev = ownPos->position.GetPrevious();
		auto &curr = *ownPos->position;
		auto &vel = *ownPos->position.Derivative();

		Point3 normal;
		float entryTime = 0.0f;

		auto pair = engine->objects.right.equal_range(&typeid(BoundingComponent));

		/* loop until all collisions have been resolved */
		while(entryTime != 1.0f) {
			auto tickVel = vel * delta.float_;
			entryTime = 1.0f;

			/* find collision with soonest entry time */
			for(auto it = pair.first; it != pair.second; ++it) {
				auto id = it->get_left();

				/* don't check for collisions with self */
				if(id == object) { continue; }

				auto objPos = engine->GetComponent<PositionComponent>(id);
				if(objPos != nullptr) {
					auto objBounds = engine->GetComponent<BoundingComponent>(id);
					if(objBounds != nullptr) {
						auto r = ownBounds->box.AABBSwept(objBounds->box, std::make_tuple(prev, curr, tickVel), *objPos->position);
						if(std::get<0>(r) < entryTime) { std::tie(entryTime, normal) = r; }
					}
				}
			}

			/* respond to collision */
			if(entryTime < 1.0f) {
				/* project previous position to point of entry of collision */
				prev += tickVel * entryTime;

				/* project position onto surface by subtracting surface-to-end vector */
				curr -= normal * glm::dot(tickVel, normal);

				/* project velocity onto surface too
				 * y is given a bounce factor of 0.125
				 */
				vel -= normal * glm::dot(Point3(vel.x, vel.y * 1.125f, vel.z), normal);
			}
		}
	});
}

void PlayerController::Update(DeltaTicks &dt) {
	auto ownPos = engine->GetComponent<PositionComponent>(object);
	auto ownOrient = engine->GetComponent<OrientationComponent>(object);

	auto rel = glm::normalize(Point4((moveLeft ? -1 : 0) + (moveRight ? 1 : 0), 0, (moveForward ? -1 : 0) + (moveBackward ? 1 : 0), 1));
	auto abs = (glm::inverse(ownOrient->orientation) * rel) * 3.5f; /* 4 meters per second */

	ownPos->position.Derivative()->x = abs.x;
	//pos->position.Derivative()->y = abs.y;
	ownPos->position.Derivative()->z = abs.z;
}
<|endoftext|>


<commit_before>//
// C++ Implementation: localbero
//
// Description:
//
//
// Author: FThauer FHammer <webmaster@pokerth.net>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "localbero.h"

using namespace std;

LocalBeRo::LocalBeRo(HandInterface* hi, int id, unsigned dP, int sB, GameState gS)
: BeRoInterface(), myHand(hi), myBeRoID(gS), myID(id), dealerPosition(dP), smallBlindPosition(0), dealerPositionId(dP), smallBlindPositionId(0), bigBlindPositionId(0), smallBlind(sB), highestSet(false), minimumRaise(2*sB), firstRun(true), firstRound(true), firstHeadsUpRound(true), currentPlayersTurnId(0), firstRoundLastPlayersTurnId(0), logBoardCardsDone(false)
{
	currentPlayersTurnIt = myHand->getRunningPlayerList()->begin();
	lastPlayersTurnIt = myHand->getRunningPlayerList()->begin();

	PlayerListConstIterator it_c;

	// determine bigBlindPosition
	for(it_c=myHand->getActivePlayerList()->begin(); it_c!=myHand->getActivePlayerList()->end(); it_c++) {
		if((*it_c)->getMyButton() == BUTTON_BIG_BLIND) {
			bigBlindPositionId = (*it_c)->getMyUniqueID();
			break;
		}
	}
	assert(it_c!=myHand->getActivePlayerList()->end());

	// determine smallBlindPosition
	for(it_c=myHand->getActivePlayerList()->begin(); it_c!=myHand->getActivePlayerList()->end(); it_c++) {
		if((*it_c)->getMyButton() == BUTTON_SMALL_BLIND) {
			smallBlindPositionId = (*it_c)->getMyUniqueID();
			break;
		}
	}
	assert(it_c!=myHand->getActivePlayerList()->end());

// 	int i;

	//SmallBlind-Position ermitteln
// 	for(i=0; i<MAX_NUMBER_OF_PLAYERS; i++) {
// 		if (myHand->getPlayerArray()[i]->getMyButton() == 2) smallBlindPosition = i;
// 	}

}

LocalBeRo::~LocalBeRo()
{
}

void LocalBeRo::nextPlayer() {

// 	myHand->getPlayerArray()[playersTurn]->action();

// 	cout << "playerID in nextPlayer(): " << (*currentPlayersTurnIt)->getMyID() << endl;

	PlayerListConstIterator currentPlayersTurnConstIt = myHand->getRunningPlayerIt(currentPlayersTurnId);
	assert( currentPlayersTurnConstIt != myHand->getRunningPlayerList()->end() );

	(*currentPlayersTurnConstIt)->action();

}

void LocalBeRo::run() {

	int i;
	PlayerListIterator it;

	if (firstRun) {

		// determine smallBlindPosition
		PlayerListIterator smallBlindPositionIt;

		for(smallBlindPositionIt=myHand->getActivePlayerList()->begin(); smallBlindPositionIt!=myHand->getActivePlayerList()->end(); smallBlindPositionIt++) {
			if((*smallBlindPositionIt)->getMyButton() == BUTTON_SMALL_BLIND) break;
		}

		// determine running player before smallBlind (for heads up: determine dealer/smallblind)
		PlayerListIterator it_1, it_2;
		size_t i;

		// running player before smallBlind
		if(myHand->getActivePlayerList()->size() > 2) {
			it_1 = smallBlindPositionIt;
			for(i=0; i<myHand->getActivePlayerList()->size(); i++) {
				if(it_1 == myHand->getActivePlayerList()->begin()) it_1 = myHand->getActivePlayerList()->end();
				it_1--;
				it_2 = find(myHand->getRunningPlayerList()->begin(), myHand->getRunningPlayerList()->end(), *it_1);
				// running player found
				if(it_2 != myHand->getRunningPlayerList()->end()) {
					lastPlayersTurnIt = it_2;
					break;
				}
			}
		}
		// heads up: bigBlind begins -> dealer/smallBlind is running player before bigBlind
		else {
			it_1 = find(myHand->getRunningPlayerList()->begin(), myHand->getRunningPlayerList()->end(), *smallBlindPositionIt);
			if( it_1 == myHand->getRunningPlayerList()->end() ) {
				cout << "ERROR - lastPlayersTurnIt-detection in localBeRo" << endl;
			}
			// smallBlind found
			else {
				lastPlayersTurnIt = it_1;
			}
		}

		currentPlayersTurnIt = lastPlayersTurnIt;

		myHand->getGuiInterface()->dealBeRoCards(myBeRoID);
		firstRun = false;

	}

	else {
		//log the turned cards
		if(!logBoardCardsDone) {

			int tempBoardCardsArray[5];

			myHand->getBoard()->getMyCards(tempBoardCardsArray);

			switch(myBeRoID) {
				case GAME_STATE_FLOP: myHand->getGuiInterface()->logDealBoardCardsMsg(myBeRoID, tempBoardCardsArray[0], tempBoardCardsArray[1], tempBoardCardsArray[2]);
				break;
				case GAME_STATE_TURN: myHand->getGuiInterface()->logDealBoardCardsMsg(myBeRoID, tempBoardCardsArray[0], tempBoardCardsArray[1], tempBoardCardsArray[2], tempBoardCardsArray[3]);
				break;
				case GAME_STATE_RIVER: myHand->getGuiInterface()->logDealBoardCardsMsg(myBeRoID, tempBoardCardsArray[0], tempBoardCardsArray[1], tempBoardCardsArray[2], tempBoardCardsArray[3], tempBoardCardsArray[4]);
				break;
				default: { cout << "ERROR in localbero.cpp - wrong myBeRoID" << endl;}
			}
			logBoardCardsDone = true;

		}

		bool allHighestSet = true;

		// prfe, ob alle Sets gleich sind ( falls nicht, dann allHighestSet = 0 )
// 		for(i=0; i<MAX_NUMBER_OF_PLAYERS; i++) {
// 			if(myHand->getPlayerArray()[i]->getMyActiveStatus() && myHand->getPlayerArray()[i]->getMyAction() != 1 && myHand->getPlayerArray()[i]->getMyAction() != 6)	{
// 				if(highestSet != myHand->getPlayerArray()[i]->getMySet()) { allHighestSet=0; }
// 			}
// 		}

		// test if all running players have same sets (else allHighestSet = false)
		for(it=myHand->getRunningPlayerList()->begin(); it!=myHand->getRunningPlayerList()->end(); it++) {
			if(highestSet != (*it)->getMySet()) {
				allHighestSet = false;
			}
		}

		// prfen, ob aktuelle bero wirklich dran ist
		if(!firstRound && allHighestSet) {

			// aktuelle bero nicht dran, weil alle Sets gleich sind
			//also gehe in naechste bero
			myHand->setActualRound(myBeRoID+1);

			//Action loeschen und ActionButtons refresh
// 			for(i=0; i<MAX_NUMBER_OF_PLAYERS; i++) {
// 				if(myHand->getPlayerArray()[i]->getMyAction() != 1 && myHand->getPlayerArray()[i]->getMyAction() != 6) myHand->getPlayerArray()[i]->setMyAction(0);
// 			}

			//Action loeschen und ActionButtons refresh
			for(it=myHand->getRunningPlayerList()->begin(); it!=myHand->getRunningPlayerList()->end(); it++) {
				(*it)->setMyAction(PLAYER_ACTION_NONE);
			}

			//Sets in den Pot verschieben und Sets = 0 und Pot-refresh
			myHand->getBoard()->collectSets();
			myHand->getBoard()->collectPot();
			myHand->getGuiInterface()->refreshPot();

			myHand->getGuiInterface()->refreshSet();
			myHand->getGuiInterface()->refreshCash();
			for(i=0; i<MAX_NUMBER_OF_PLAYERS; i++) { myHand->getGuiInterface()->refreshAction(i,PLAYER_ACTION_NONE); }

			myHand->switchRounds();
		}
		else {
			// aktuelle bero ist wirklich dran

			// Anzahl der effektiv gespielten Runden (des human player) erhöhen
			if(myHand->getPlayerArray()[0]->getMyActiveStatus() && myHand->getPlayerArray()[0]->getMyAction() != 1) {
				myHand->setBettingRoundsPlayed(myBeRoID);
			}

			//// !!!!!!!!!!!!!!!!1!!!! very buggy, rule breaking -> TODO !!!!!!!!!!!!11!!!!!!!! //////////////

			//// headsup:
			//// preflop: dealer is small blind and begins
			//// flop, trun, river: big blind begins

			//// !!!!!!!!! attention: exception if player failed before !!!!!!!!

// 			if( !(myHand->getActualQuantityPlayers() < 3 && firstHeadsUpRound == 1) || myHand->getPlayerArray()[playersTurn]->getMyActiveStatus() == 0 ) {
// 			not first round in heads up (for headsup dealer is smallblind so it is dealers turn)

				// naechsten Spieler ermitteln
// 				int i;
// 				for(i=0; (i<MAX_NUMBER_OF_PLAYERS && ((myHand->getPlayerArray()[playersTurn]->getMyActiveStatus()) == 0 || (myHand->getPlayerArray()[playersTurn]->getMyAction())==1 || (myHand->getPlayerArray()[playersTurn]->getMyAction())==6)) || i==0; i++) {
// 					playersTurn = (playersTurn+1)%(MAX_NUMBER_OF_PLAYERS);
// 				}
// 				firstHeadsUpRound = 0;

				// determine next running player
				currentPlayersTurnIt++;
				if(currentPlayersTurnIt == myHand->getRunningPlayerList()->end()) currentPlayersTurnIt = myHand->getRunningPlayerList()->begin();

// 			}
// 			else { firstHeadsUpRound = 0; }

			////// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ////////////////

			//Spieler-Position vor SmallBlind-Position ermitteln
// 			int activePlayerBeforeSmallBlind = smallBlindPosition;

// 			for(i=0; (i<MAX_NUMBER_OF_PLAYERS && !(myHand->getPlayerArray()[activePlayerBeforeSmallBlind]->getMyActiveStatus()) || (myHand->getPlayerArray()[activePlayerBeforeSmallBlind]->getMyAction())==1 || (myHand->getPlayerArray()[activePlayerBeforeSmallBlind]->getMyAction())==6) || i==0; i++) {

// 				activePlayerBeforeSmallBlind = (activePlayerBeforeSmallBlind + MAX_NUMBER_OF_PLAYERS - 1 ) % (MAX_NUMBER_OF_PLAYERS);
// 			}

// 			myHand->getPlayerArray()[playersTurn]->setMyTurn(1);

			(*currentPlayersTurnIt)->setMyTurn(true);

			//highlight active players groupbox and clear action
			myHand->getGuiInterface()->refreshGroupbox((*currentPlayersTurnIt)->getMyID(),2);
			myHand->getGuiInterface()->refreshAction((*currentPlayersTurnIt)->getMyID(),0);

			// wenn wir letzter aktiver Spieler vor SmallBlind sind, dann flopFirstRound zuende
			// ausnahme bei heads up !!! --> TODO
// 			if(myHand->getPlayerArray()[playersTurn]->getMyID() == activePlayerBeforeSmallBlind && myHand->getActivePlayerList()->size() >= 3) { firstRound = 0; }
// 			if(myHand->getActivePlayerList()->size() < 3 && (myHand->getPlayerArray()[playersTurn]->getMyID() == dealerPosition || myHand->getPlayerArray()[playersTurn]->getMyID() == smallBlindPosition)) { firstRound = 0; }

			if( (*currentPlayersTurnIt) == (*lastPlayersTurnIt) ) {
				firstRound = false;
			}

			if((*currentPlayersTurnIt)->getMyID() == 0) {
				// Wir sind dran
				myHand->getGuiInterface()->meInAction();
			}
			else {
				//Gegner sind dran
				myHand->getGuiInterface()->beRoAnimation2(myBeRoID);
			}
		}
	}
}

<commit_msg>adds activePlayerList and runningPlayerList (XV) - !!! BROKEN !!! - last sable rev866<commit_after>//
// C++ Implementation: localbero
//
// Description:
//
//
// Author: FThauer FHammer <webmaster@pokerth.net>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "localbero.h"

using namespace std;

LocalBeRo::LocalBeRo(HandInterface* hi, int id, unsigned dP, int sB, GameState gS)
: BeRoInterface(), myHand(hi), myBeRoID(gS), myID(id), dealerPosition(dP), smallBlindPosition(0), dealerPositionId(dP), smallBlindPositionId(0), bigBlindPositionId(0), smallBlind(sB), highestSet(false), minimumRaise(2*sB), firstRun(true), firstRound(true), firstHeadsUpRound(true), currentPlayersTurnId(0), firstRoundLastPlayersTurnId(0), logBoardCardsDone(false)
{
	currentPlayersTurnIt = myHand->getRunningPlayerList()->begin();
	lastPlayersTurnIt = myHand->getRunningPlayerList()->begin();

	PlayerListConstIterator it_c;

	// determine bigBlindPosition
	for(it_c=myHand->getActivePlayerList()->begin(); it_c!=myHand->getActivePlayerList()->end(); it_c++) {
		if((*it_c)->getMyButton() == BUTTON_BIG_BLIND) {
			bigBlindPositionId = (*it_c)->getMyUniqueID();
			break;
		}
	}
	assert(it_c!=myHand->getActivePlayerList()->end());

	// determine smallBlindPosition
	for(it_c=myHand->getActivePlayerList()->begin(); it_c!=myHand->getActivePlayerList()->end(); it_c++) {
		if((*it_c)->getMyButton() == BUTTON_SMALL_BLIND) {
			smallBlindPositionId = (*it_c)->getMyUniqueID();
			break;
		}
	}
	assert(it_c!=myHand->getActivePlayerList()->end());

// 	int i;

	//SmallBlind-Position ermitteln
// 	for(i=0; i<MAX_NUMBER_OF_PLAYERS; i++) {
// 		if (myHand->getPlayerArray()[i]->getMyButton() == 2) smallBlindPosition = i;
// 	}

}

LocalBeRo::~LocalBeRo()
{
}

void LocalBeRo::nextPlayer() {

// 	myHand->getPlayerArray()[playersTurn]->action();

// 	cout << "playerID in nextPlayer(): " << (*currentPlayersTurnIt)->getMyID() << endl;

	PlayerListConstIterator currentPlayersTurnConstIt = myHand->getRunningPlayerIt(currentPlayersTurnId);
	assert( currentPlayersTurnConstIt != myHand->getRunningPlayerList()->end() );

	(*currentPlayersTurnConstIt)->action();

}

void LocalBeRo::run() {

	int i;
	PlayerListIterator it;

	if (firstRun) {

/*

// 	PlayerListIterator it;

	// search bigBlindPosition in runningPlayerList -> old: delete
// 	it_1 = find(getMyHand()->getRunningPlayerList()->begin(), getMyHand()->getRunningPlayerList()->end(), *bigBlindPositionIt);

	// search bigBlindPosition in runningPlayerList
// 	PlayerListIterator bigBlindPositionIt = getMyHand()->getRunningPlayerIt(getBigBlindPositionId());

	// more than 2 players are still active -> runningPlayerList is not empty
	if(getMyHand()->getActivePlayerList()->size() > 2) {

		// bigBlindPlayer not found in runningPlayerList (he is all in) -> bigBlindPlayer is not the running player before first action player
		if(bigBlindPositionIt == getMyHand()->getRunningPlayerList()->end()) {

			// search smallBlindPosition in runningPlayerList
			PlayerListIterator smallBlindPositionIt = getMyHand()->getRunningPlayerIt(getSmallBlindPositionId());
// 			if(smallBlindPositionIt == getMyHand()->getActivePlayerList()->begin()) smallBlindPositionIt = getMyHand()->getActivePlayerList()->end();
// 			smallBlindPositionIt--;
// 			it_2 = find(getMyHand()->getRunningPlayerList()->begin(), getMyHand()->getRunningPlayerList()->end(), *smallBlindPositionIt);

			// smallBlindPlayer not found in runningPlayerList (he is all in) -> next active player before smallBlindPlayer is running player before first action player
			if(smallBlindPositionIt == getMyHand()->getRunningPlayerList()->end()) {

				it = getMyHand()->getActivePlayerIt(getSmallBlindPositionId());
				assert(it != getMyHand()->getActivePlayerList()->end());

				if(it == getMyHand()->getActivePlayerList()->begin()) it = getMyHand()->getActivePlayerList()->end();
				it--;

				setFirstRoundLastPlayersTurnId( (*it)->getMyUniqueID() );

// 				it_3 = find(getMyHand()->getRunningPlayerList()->begin(), getMyHand()->getRunningPlayerList()->end(), *it_2);
// 				if(it_3 == getMyHand()->getRunningPlayerList()->end()) {
// 					cout << "ERROR - lastPlayersTurnIt-detection in localBeRoPreflop" << endl;
// 				} else {
// 					setLastPlayersTurnIt(it_3);
// 				}
			}
			// smallBlindPlayer found in runningPlayerList -> running player before first action player
			else {
				setFirstRoundLastPlayersTurnId( getSmallBlindPositionId() );
			}
		}
		// bigBlindPlayer found in runningPlayerList -> player before first action player
		else {
			setFirstRoundLastPlayersTurnId( getBigBlindPositionId() );
		}
	}
	// heads up -> dealer/smallBlindPlayer is first action player and bigBlindPlayer is player before
	else {

		// bigBlindPlayer not found in runningPlayerList (he is all in) -> only smallBlind has to choose fold or call the bigBlindAmount
		if(bigBlindPositionIt == getMyHand()->getRunningPlayerList()->end()) {

			// search smallBlindPosition in runningPlayerList
			PlayerListIterator smallBlindPositionIt = getMyHand()->getRunningPlayerIt(getSmallBlindPositionId());

			// smallBlindPlayer not found in runningPlayerList (he is all in) -> no running player -> showdown and no firstRoundLastPlayersTurnId is used
			if(smallBlindPositionIt == getMyHand()->getRunningPlayerList()->end()) {

			}
			// smallBlindPlayer found in runningPlayerList -> running player before first action player (himself)
			else {
				setFirstRoundLastPlayersTurnId( getSmallBlindPositionId() );
			}

		}
		setFirstRoundLastPlayersTurnId( getBigBlindPositionId() );
	}

	setCurrentPlayersTurnId( getFirstRoundLastPlayersTurnId() );

		// determine smallBlindPosition
		PlayerListIterator smallBlindPositionIt;

		for(smallBlindPositionIt=myHand->getActivePlayerList()->begin(); smallBlindPositionIt!=myHand->getActivePlayerList()->end(); smallBlindPositionIt++) {
			if((*smallBlindPositionIt)->getMyButton() == BUTTON_SMALL_BLIND) break;
		}

		// determine running player before smallBlind (for heads up: determine dealer/smallblind)
		PlayerListIterator it_1, it_2;
		size_t i;

		// running player before smallBlind
		if(myHand->getActivePlayerList()->size() > 2) {
			it_1 = smallBlindPositionIt;
			for(i=0; i<myHand->getActivePlayerList()->size(); i++) {
				if(it_1 == myHand->getActivePlayerList()->begin()) it_1 = myHand->getActivePlayerList()->end();
				it_1--;
				it_2 = find(myHand->getRunningPlayerList()->begin(), myHand->getRunningPlayerList()->end(), *it_1);
				// running player found
				if(it_2 != myHand->getRunningPlayerList()->end()) {
					lastPlayersTurnIt = it_2;
					break;
				}
			}
		}
		// heads up: bigBlind begins -> dealer/smallBlind is running player before bigBlind
		else {
			it_1 = find(myHand->getRunningPlayerList()->begin(), myHand->getRunningPlayerList()->end(), *smallBlindPositionIt);
			if( it_1 == myHand->getRunningPlayerList()->end() ) {
				cout << "ERROR - lastPlayersTurnIt-detection in localBeRo" << endl;
			}
			// smallBlind found
			else {
				lastPlayersTurnIt = it_1;
			}
		}

		currentPlayersTurnIt = lastPlayersTurnIt;

*/

		// determine smallBlindPosition
// 		PlayerListIterator smallBlindPositionIt;

// 		for(smallBlindPositionIt=myHand->getActivePlayerList()->begin(); smallBlindPositionIt!=myHand->getActivePlayerList()->end(); smallBlindPositionIt++) {
// 			if((*smallBlindPositionIt)->getMyButton() == BUTTON_SMALL_BLIND) break;
// 		}

		// determine running player before smallBlind (for heads up: determine dealer/smallblind)
		PlayerListIterator it_1, it_2;
		size_t i;

		// running player before smallBlind
		if(myHand->getActivePlayerList()->size() > 2) {
			it_1 = myHand->getActivePlayerIt(smallBlindPositionId);
			assert( it_1 != myHand->getActivePlayerList()->end() );
			for(i=0; i<myHand->getActivePlayerList()->size(); i++) {
				if(it_1 == myHand->getActivePlayerList()->begin()) it_1 = myHand->getActivePlayerList()->end();
				it_1--;
				it_2 = find(myHand->getRunningPlayerList()->begin(), myHand->getRunningPlayerList()->end(), *it_1);
				// running player found
				if(it_2 != myHand->getRunningPlayerList()->end()) {
					lastPlayersTurnIt = it_2;
					break;
				}
			}
		}
		// heads up: bigBlind begins -> dealer/smallBlind is running player before bigBlind
		else {
			//TODO
// 			it_1 = find(myHand->getRunningPlayerList()->begin(), myHand->getRunningPlayerList()->end(), *smallBlindPositionIt);
			if( it_1 == myHand->getRunningPlayerList()->end() ) {
				cout << "ERROR - lastPlayersTurnIt-detection in localBeRo" << endl;
			}
			// smallBlind found
			else {
				lastPlayersTurnIt = it_1;
			}
		}

		currentPlayersTurnIt = lastPlayersTurnIt;

		myHand->getGuiInterface()->dealBeRoCards(myBeRoID);
		firstRun = false;

	}

	else {
		//log the turned cards
		if(!logBoardCardsDone) {

			int tempBoardCardsArray[5];

			myHand->getBoard()->getMyCards(tempBoardCardsArray);

			switch(myBeRoID) {
				case GAME_STATE_FLOP: myHand->getGuiInterface()->logDealBoardCardsMsg(myBeRoID, tempBoardCardsArray[0], tempBoardCardsArray[1], tempBoardCardsArray[2]);
				break;
				case GAME_STATE_TURN: myHand->getGuiInterface()->logDealBoardCardsMsg(myBeRoID, tempBoardCardsArray[0], tempBoardCardsArray[1], tempBoardCardsArray[2], tempBoardCardsArray[3]);
				break;
				case GAME_STATE_RIVER: myHand->getGuiInterface()->logDealBoardCardsMsg(myBeRoID, tempBoardCardsArray[0], tempBoardCardsArray[1], tempBoardCardsArray[2], tempBoardCardsArray[3], tempBoardCardsArray[4]);
				break;
				default: { cout << "ERROR in localbero.cpp - wrong myBeRoID" << endl;}
			}
			logBoardCardsDone = true;

		}

		bool allHighestSet = true;

		// prfe, ob alle Sets gleich sind ( falls nicht, dann allHighestSet = 0 )
// 		for(i=0; i<MAX_NUMBER_OF_PLAYERS; i++) {
// 			if(myHand->getPlayerArray()[i]->getMyActiveStatus() && myHand->getPlayerArray()[i]->getMyAction() != 1 && myHand->getPlayerArray()[i]->getMyAction() != 6)	{
// 				if(highestSet != myHand->getPlayerArray()[i]->getMySet()) { allHighestSet=0; }
// 			}
// 		}

		// test if all running players have same sets (else allHighestSet = false)
		for(it=myHand->getRunningPlayerList()->begin(); it!=myHand->getRunningPlayerList()->end(); it++) {
			if(highestSet != (*it)->getMySet()) {
				allHighestSet = false;
			}
		}

		// prfen, ob aktuelle bero wirklich dran ist
		if(!firstRound && allHighestSet) {

			// aktuelle bero nicht dran, weil alle Sets gleich sind
			//also gehe in naechste bero
			myHand->setActualRound(myBeRoID+1);

			//Action loeschen und ActionButtons refresh
// 			for(i=0; i<MAX_NUMBER_OF_PLAYERS; i++) {
// 				if(myHand->getPlayerArray()[i]->getMyAction() != 1 && myHand->getPlayerArray()[i]->getMyAction() != 6) myHand->getPlayerArray()[i]->setMyAction(0);
// 			}

			//Action loeschen und ActionButtons refresh
			for(it=myHand->getRunningPlayerList()->begin(); it!=myHand->getRunningPlayerList()->end(); it++) {
				(*it)->setMyAction(PLAYER_ACTION_NONE);
			}

			//Sets in den Pot verschieben und Sets = 0 und Pot-refresh
			myHand->getBoard()->collectSets();
			myHand->getBoard()->collectPot();
			myHand->getGuiInterface()->refreshPot();

			myHand->getGuiInterface()->refreshSet();
			myHand->getGuiInterface()->refreshCash();
			for(i=0; i<MAX_NUMBER_OF_PLAYERS; i++) { myHand->getGuiInterface()->refreshAction(i,PLAYER_ACTION_NONE); }

			myHand->switchRounds();
		}
		else {
			// aktuelle bero ist wirklich dran

			// Anzahl der effektiv gespielten Runden (des human player) erhöhen
			if(myHand->getPlayerArray()[0]->getMyActiveStatus() && myHand->getPlayerArray()[0]->getMyAction() != 1) {
				myHand->setBettingRoundsPlayed(myBeRoID);
			}

			//// !!!!!!!!!!!!!!!!1!!!! very buggy, rule breaking -> TODO !!!!!!!!!!!!11!!!!!!!! //////////////

			//// headsup:
			//// preflop: dealer is small blind and begins
			//// flop, trun, river: big blind begins

			//// !!!!!!!!! attention: exception if player failed before !!!!!!!!

// 			if( !(myHand->getActualQuantityPlayers() < 3 && firstHeadsUpRound == 1) || myHand->getPlayerArray()[playersTurn]->getMyActiveStatus() == 0 ) {
// 			not first round in heads up (for headsup dealer is smallblind so it is dealers turn)

				// naechsten Spieler ermitteln
// 				int i;
// 				for(i=0; (i<MAX_NUMBER_OF_PLAYERS && ((myHand->getPlayerArray()[playersTurn]->getMyActiveStatus()) == 0 || (myHand->getPlayerArray()[playersTurn]->getMyAction())==1 || (myHand->getPlayerArray()[playersTurn]->getMyAction())==6)) || i==0; i++) {
// 					playersTurn = (playersTurn+1)%(MAX_NUMBER_OF_PLAYERS);
// 				}
// 				firstHeadsUpRound = 0;

				// determine next running player
				currentPlayersTurnIt++;
				if(currentPlayersTurnIt == myHand->getRunningPlayerList()->end()) currentPlayersTurnIt = myHand->getRunningPlayerList()->begin();

// 			}
// 			else { firstHeadsUpRound = 0; }

			////// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ////////////////

			//Spieler-Position vor SmallBlind-Position ermitteln
// 			int activePlayerBeforeSmallBlind = smallBlindPosition;

// 			for(i=0; (i<MAX_NUMBER_OF_PLAYERS && !(myHand->getPlayerArray()[activePlayerBeforeSmallBlind]->getMyActiveStatus()) || (myHand->getPlayerArray()[activePlayerBeforeSmallBlind]->getMyAction())==1 || (myHand->getPlayerArray()[activePlayerBeforeSmallBlind]->getMyAction())==6) || i==0; i++) {

// 				activePlayerBeforeSmallBlind = (activePlayerBeforeSmallBlind + MAX_NUMBER_OF_PLAYERS - 1 ) % (MAX_NUMBER_OF_PLAYERS);
// 			}

// 			myHand->getPlayerArray()[playersTurn]->setMyTurn(1);

			(*currentPlayersTurnIt)->setMyTurn(true);

			//highlight active players groupbox and clear action
			myHand->getGuiInterface()->refreshGroupbox((*currentPlayersTurnIt)->getMyID(),2);
			myHand->getGuiInterface()->refreshAction((*currentPlayersTurnIt)->getMyID(),0);

			// wenn wir letzter aktiver Spieler vor SmallBlind sind, dann flopFirstRound zuende
			// ausnahme bei heads up !!! --> TODO
// 			if(myHand->getPlayerArray()[playersTurn]->getMyID() == activePlayerBeforeSmallBlind && myHand->getActivePlayerList()->size() >= 3) { firstRound = 0; }
// 			if(myHand->getActivePlayerList()->size() < 3 && (myHand->getPlayerArray()[playersTurn]->getMyID() == dealerPosition || myHand->getPlayerArray()[playersTurn]->getMyID() == smallBlindPosition)) { firstRound = 0; }

			if( (*currentPlayersTurnIt) == (*lastPlayersTurnIt) ) {
				firstRound = false;
			}

			if((*currentPlayersTurnIt)->getMyID() == 0) {
				// Wir sind dran
				myHand->getGuiInterface()->meInAction();
			}
			else {
				//Gegner sind dran
				myHand->getGuiInterface()->beRoAnimation2(myBeRoID);
			}
		}
	}
}

<|endoftext|>