summaryrefslogtreecommitdiffstats
path: root/sigbattle
diff options
context:
space:
mode:
authorBen Boeckel <MathStuf@gmail.com>2008-09-05 20:41:05 +0000
committerBen Boeckel <MathStuf@gmail.com>2008-09-05 20:41:05 +0000
commitb81f5bffa2772eb9bd3c67fb35485ab1ee2d96e7 (patch)
tree6609f31b1635d948cf7a216c7fea72cfb3c905a0 /sigbattle
parentb99ffef4aa68dd5f0af64de9aec0f610e267d8cc (diff)
downloadsigen-b81f5bffa2772eb9bd3c67fb35485ab1ee2d96e7.tar.gz
sigen-b81f5bffa2772eb9bd3c67fb35485ab1ee2d96e7.tar.xz
sigen-b81f5bffa2772eb9bd3c67fb35485ab1ee2d96e7.zip
[FIX] Moving stuff for the move to the new name, Sigma Game Engine (sigen for short)
git-svn-id: https://pokegen.svn.sourceforge.net/svnroot/pokegen/trunk@249 6ecfd1a5-f3ed-3746-8530-beee90d26b22
Diffstat (limited to 'sigbattle')
-rw-r--r--sigbattle/ATBArena.cpp62
-rw-r--r--sigbattle/ATBArena.h50
-rw-r--r--sigbattle/ATBTimer.cpp72
-rw-r--r--sigbattle/ATBTimer.h61
-rw-r--r--sigbattle/ActionQueue.h83
-rw-r--r--sigbattle/Arena.cpp117
-rw-r--r--sigbattle/Arena.h84
-rw-r--r--sigbattle/Bot.h55
-rw-r--r--sigbattle/CMakeLists.txt70
-rw-r--r--sigbattle/Containment.cpp34
-rw-r--r--sigbattle/Containment.h59
-rw-r--r--sigbattle/Ghost.cpp94
-rw-r--r--sigbattle/Ghost.h65
-rw-r--r--sigbattle/GhostBot.h32
-rw-r--r--sigbattle/Global.h38
-rw-r--r--sigbattle/Player.cpp41
-rw-r--r--sigbattle/Player.h63
-rw-r--r--sigbattle/TODO1
-rw-r--r--sigbattle/Team.cpp73
-rw-r--r--sigbattle/Team.h47
-rw-r--r--sigbattle/TeamMember.cpp637
-rw-r--r--sigbattle/TeamMember.h207
-rw-r--r--sigbattle/TurnArena.cpp101
-rw-r--r--sigbattle/TurnArena.h59
24 files changed, 2205 insertions, 0 deletions
diff --git a/sigbattle/ATBArena.cpp b/sigbattle/ATBArena.cpp
new file mode 100644
index 00000000..92a1b71e
--- /dev/null
+++ b/sigbattle/ATBArena.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header includes
+#include "ATBArena.h"
+
+// Pokebattle includes
+#include "ATBTimer.h"
+
+// Qt includes
+#include <QtCore/QTimer>
+
+Pokebattle::ATBArena::ATBArena(QList<Player*> players, QObject* parent) :
+ Arena(players, parent)
+{
+ setupBattle();
+}
+
+void Pokebattle::ATBArena::handleAction(TeamMember* teamMember, TeamMember::Action action)
+{
+ if (action.first == TeamMember::Skip)
+ {
+ m_decisions.enqueue(requestDecision(teamMember));
+ return;
+ }
+ Arena::handleAction(teamMember, action);
+}
+
+void Pokebattle::ATBArena::processActions()
+{
+ if (!m_decisions.isEmpty())
+ {
+ while (m_decisions.head().second.isFinished())
+ {
+ TeamMember::RequestedAction action = m_decisions.dequeue();
+ handleAction(action.first, action.second.result());
+ }
+ }
+}
+
+void Pokebattle::ATBArena::setupBattle()
+{
+ m_atbTimer = new ATBTimer(this, m_decisions);
+ QTimer* moveTimer = new QTimer(this);
+ connect(moveTimer, SIGNAL(timeout()), this, SLOT(processActions()));
+ moveTimer->start(100);
+ Arena::setupBattle();
+}
diff --git a/sigbattle/ATBArena.h b/sigbattle/ATBArena.h
new file mode 100644
index 00000000..7cb095ec
--- /dev/null
+++ b/sigbattle/ATBArena.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_ATBARENA__
+#define __POKEBATTLE_ATBARENA__
+
+// Pokebattle includes
+#include "ActionQueue.h"
+#include "Arena.h"
+
+namespace Pokebattle
+{
+// Forward declaraions
+class ATBTimer;
+
+class POKEBATTLE_EXPORT ATBArena : public Arena
+{
+ Q_OBJECT
+
+ public:
+ ATBArena(QList<Player*> players, QObject* parent);
+
+ void handleAction(TeamMember* teamMember, TeamMember::Action action);
+ signals:
+ public slots:
+ protected slots:
+ void processActions();
+ protected:
+ void setupBattle();
+ private:
+ ActionQueue m_decisions;
+ ATBTimer* m_atbTimer;
+};
+}
+
+#endif
diff --git a/sigbattle/ATBTimer.cpp b/sigbattle/ATBTimer.cpp
new file mode 100644
index 00000000..d2f42ce2
--- /dev/null
+++ b/sigbattle/ATBTimer.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "ATBTimer.h"
+
+// Pokebattle includes
+#include "ATBArena.h"
+
+// Qt includes
+#include <QtCore/QtConcurrentFilter>
+#include <QtCore/QtConcurrentMap>
+#include <QtCore/QFuture>
+#include <QtCore/QMultiMap>
+#include <QtCore/QTimer>
+
+// STL includes
+#include <functional>
+
+Pokebattle::ATBTimer::ATBTimer(ATBArena* arena, ActionQueue& actions) :
+ QThread(arena),
+ m_arena(arena),
+ m_actions(actions),
+ m_timer(new QTimer(this))
+{
+ connect(m_timer, SIGNAL(timeout()), this, SLOT(update()));
+}
+
+void Pokebattle::ATBTimer::update()
+{
+ const QList<TeamMember*> active = m_timeStates.keys();
+ QtConcurrent::blockingMap(active, std::bind1st(std::mem_fun(&Pokebattle::ATBTimer::increaseMeter), this));
+ // TODO: adjust max time if needed
+ QList<TeamMember*> overflow = QtConcurrent::blockingFiltered(active, std::bind1st(std::mem_fun(&Pokebattle::ATBTimer::isOverflowed), this));
+ QMultiMap<double, TeamMember*> sorter;
+ foreach (TeamMember* teamMember, overflow)
+ sorter.insert(m_timeStates[teamMember], teamMember);
+ overflow = sorter.values();
+ foreach(TeamMember* teamMember, overflow)
+ m_actions.enqueue(requestDecision(teamMember));
+}
+
+void Pokebattle::ATBTimer::run()
+{
+ m_timer->start(50);
+ exec();
+}
+
+void Pokebattle::ATBTimer::increaseMeter(const TeamMember* teamMember)
+{
+ // TODO: tweak this(?)
+ m_timeStates[const_cast<TeamMember*>(teamMember)] += teamMember->statValue(Pokemod::ST_Speed) / 10;
+}
+
+bool Pokebattle::ATBTimer::isOverflowed(const TeamMember* teamMember) const
+{
+ return m_threshold < m_timeStates[const_cast<TeamMember*>(teamMember)];
+}
diff --git a/sigbattle/ATBTimer.h b/sigbattle/ATBTimer.h
new file mode 100644
index 00000000..ff84ce54
--- /dev/null
+++ b/sigbattle/ATBTimer.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_ATBTIMER__
+#define __POKEBATTLE_ATBTIMER__
+
+// Pokebattle includes
+#include "Global.h"
+
+// Qt includes
+#include <QtCore/QMap>
+#include <QtCore/QThread>
+
+// Forward declarations
+class QTimer;
+
+namespace Pokebattle
+{
+class ActionQueue;
+class ATBArena;
+class Player;
+class TeamMember;
+
+class POKEBATTLE_EXPORT ATBTimer : public QThread
+{
+ Q_OBJECT
+
+ public:
+ ATBTimer(ATBArena* arena, ActionQueue& actions);
+ protected slots:
+ void update();
+ protected:
+ void run();
+ private:
+ void increaseMeter(const TeamMember* teamMember);
+ bool isOverflowed(const TeamMember* teamMember) const;
+
+ ATBArena* m_arena;
+ ActionQueue& m_actions;
+ QMap<TeamMember*, double> m_timeStates;
+ double m_threshold;
+ QTimer* m_timer;
+};
+
+}
+
+#endif
diff --git a/sigbattle/ActionQueue.h b/sigbattle/ActionQueue.h
new file mode 100644
index 00000000..3641755b
--- /dev/null
+++ b/sigbattle/ActionQueue.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_ACTIONQUEUE__
+#define __POKEBATTLE_ACTIONQUEUE__
+
+// Pokebattle includes
+#include "Global.h"
+#include "TeamMember.h"
+
+// Qt includes
+#include <QtCore/QMutex>
+#include <QtCore/QMutexLocker>
+#include <QtCore/QQueue>
+
+namespace Pokebattle
+{
+class POKEBATTLE_EXPORT ActionQueue : public QQueue<TeamMember::RequestedAction>
+{
+ public:
+ ActionQueue();
+
+ TeamMember::RequestedAction dequeue();
+ void enqueue(const TeamMember::RequestedAction& action);
+
+ TeamMember::RequestedAction& head();
+
+ void lock();
+ void unlock();
+ private:
+ QMutex m_mutex;
+};
+
+inline ActionQueue::ActionQueue() :
+ QQueue<TeamMember::RequestedAction>()
+{
+}
+
+inline TeamMember::RequestedAction ActionQueue::dequeue()
+{
+ QMutexLocker locker(&m_mutex);
+ return QQueue<TeamMember::RequestedAction>::dequeue();
+}
+
+inline void ActionQueue::enqueue(const TeamMember::RequestedAction& action)
+{
+ QMutexLocker locker(&m_mutex);
+ QQueue<TeamMember::RequestedAction>::enqueue(action);
+}
+
+inline TeamMember::RequestedAction& ActionQueue::head()
+{
+ QMutexLocker locker(&m_mutex);
+ return QQueue<TeamMember::RequestedAction>::head();
+}
+
+inline void ActionQueue::lock()
+{
+ m_mutex.lock();
+}
+
+inline void ActionQueue::unlock()
+{
+ m_mutex.unlock();
+}
+
+}
+
+#endif
diff --git a/sigbattle/Arena.cpp b/sigbattle/Arena.cpp
new file mode 100644
index 00000000..84c98dd9
--- /dev/null
+++ b/sigbattle/Arena.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "Arena.h"
+
+// Pokebattle includes
+#include "Player.h"
+
+// Pokemod includes
+#include "../pokemod/Script.h"
+
+// Qt includes
+#include <QtCore/QtConcurrentRun>
+
+// KDE includes
+#include <kross/core/action.h>
+#include <kross/core/actioncollection.h>
+#include <kross/core/manager.h>
+
+Pokebattle::TeamMember::RequestedAction Pokebattle::requestDecision(TeamMember* teamMember)
+{
+ return TeamMember::RequestedAction(teamMember, QtConcurrent::run(decision, teamMember));
+}
+
+Pokebattle::TeamMember::Action Pokebattle::decision(TeamMember* teamMember)
+{
+ return teamMember->requestAction();
+}
+
+Pokebattle::Arena::Arena(QList<Player*> players, QObject* parent) :
+ Pokescripting::Config(parent),
+ m_players(players),
+ m_id(QUuid::createUuid())
+{
+ connect(this, SIGNAL(battleEnd()), SLOT(cleanUp()));
+ m_actions = new Kross::ActionCollection(QString("arena-%1").arg(m_id.toString()), Kross::Manager::self().actionCollection());
+ foreach (Player* player, m_players)
+ player->enterArena(this);
+}
+
+Pokebattle::Arena::~Arena()
+{
+ delete m_actions;
+}
+
+QList<Pokebattle::TeamMember*> Pokebattle::Arena::active() const
+{
+ QList<Pokebattle::TeamMember*> active;
+ foreach (Player* player, m_players)
+ active += player->active();
+ return active;
+}
+
+int Pokebattle::Arena::numActiveTeams() const
+{
+ int active = 0;
+ foreach (Player* player, m_players)
+ active += !player->active().isEmpty();
+ return active;
+}
+
+void Pokebattle::Arena::registerScript(const QString& name, const Pokemod::Script& script)
+{
+ Kross::Action* action = new Kross::Action(m_actions, name);
+ action->setInterpreter(script.interpreter());
+ action->setCode(script.script().toUtf8());
+ action->addObject(this, "arena");
+ action->trigger();
+}
+
+void Pokebattle::Arena::cleanUp()
+{
+ // TODO: clean up everything
+}
+
+void Pokebattle::Arena::handleAction(TeamMember* teamMember, TeamMember::Action action)
+{
+ switch (action.first)
+ {
+ case TeamMember::Attack:
+ // TODO: Start move script
+ break;
+ case TeamMember::Item:
+ // TODO: Start item script
+ break;
+ case TeamMember::Switch:
+ // TODO: Switch with the other member
+ break;
+ case TeamMember::Run:
+ // TODO: Run if possible, skip if fail
+ break;
+ case TeamMember::Skip:
+ case TeamMember::Timeout:
+ case TeamMember::Invalid:
+ break;
+ }
+}
+
+void Pokebattle::Arena::setupBattle()
+{
+ // TODO: setup all the battle stuff
+}
diff --git a/sigbattle/Arena.h b/sigbattle/Arena.h
new file mode 100644
index 00000000..9a3a69e9
--- /dev/null
+++ b/sigbattle/Arena.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_ARENA__
+#define __POKEBATTLE_ARENA__
+
+// Pokebattle includes
+#include "Global.h"
+#include "Team.h"
+#include "TeamMember.h"
+
+// Qt includes
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QPair>
+#include <QtCore/QSet>
+#include <QtCore/QUuid>
+
+// Forward declarations
+namespace Kross
+{
+class Action;
+class ActionCollection;
+}
+namespace Pokemod
+{
+class Script;
+}
+
+namespace Pokebattle
+{
+class Player;
+
+class POKEBATTLE_EXPORT Arena : public Pokescripting::Config
+{
+ Q_OBJECT
+
+ public:
+ Arena(QList<Player*> players, QObject* parent);
+ ~Arena();
+
+ QList<TeamMember*> active() const;
+ int numActiveTeams() const;
+
+ Kross::Action* script(const QString& name);
+ signals:
+ void battleStart();
+ void battleEnd();
+ public slots:
+ void registerScript(const QString& name, const Pokemod::Script& script);
+ protected slots:
+ void cleanUp();
+ protected:
+ virtual void handleAction(TeamMember* teamMember, TeamMember::Action action);
+
+ virtual void setupBattle();
+
+ QList<Player*> m_players;
+ Kross::ActionCollection* m_actions;
+ private:
+ const QUuid m_id;
+};
+
+TeamMember::RequestedAction requestDecision(TeamMember* teamMember);
+TeamMember::Action decision(TeamMember* teamMember);
+
+}
+Q_DECLARE_METATYPE(Pokebattle::Arena*)
+
+#endif
diff --git a/sigbattle/Bot.h b/sigbattle/Bot.h
new file mode 100644
index 00000000..fef5d449
--- /dev/null
+++ b/sigbattle/Bot.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_BOT__
+#define __POKEBATTLE_BOT__
+
+// Pokebattle includes
+#include "Player.h"
+
+// Standard library includes
+#include <climits>
+
+// Forward declarations
+namespace Pokemod
+{
+class MapTrainer;
+}
+
+namespace Pokebattle
+{
+class Arena;
+class GhostBot;
+
+class POKEBATTLE_EXPORT Bot : public Player
+{
+ Q_OBJECT
+
+ public:
+ Bot(const Pokemod::MapTrainer& trainer);
+ signals:
+ public slots:
+ protected slots:
+ protected:
+ private:
+ long alphaBeta(const Arena& arena, const int trainerClass, const long alpha = LONG_MIN, const long beta = LONG_MAX);
+
+ QList<GhostBot*> m_enemies;
+};
+}
+
+#endif
diff --git a/sigbattle/CMakeLists.txt b/sigbattle/CMakeLists.txt
new file mode 100644
index 00000000..ec6ebcc8
--- /dev/null
+++ b/sigbattle/CMakeLists.txt
@@ -0,0 +1,70 @@
+PROJECT(pokebattle)
+
+IF(NOT BUILT_FROM_ROOT)
+ MESSAGE(FATAL_ERROR "Not built from source root")
+ENDIF(NOT BUILT_FROM_ROOT)
+
+ADD_DEFINITIONS(-DMAKE_POKEBATTLE_LIB)
+
+SET(pokebattle_MOC_HEADERS
+ Arena.h
+ ATBArena.h
+ ATBTimer.h
+ Bot.h
+ Containment.h
+ GhostBot.h
+ Ghost.h
+ Player.h
+ Team.h
+ TeamMember.h
+ TurnArena.h
+)
+QT4_WRAP_CPP(pokebattle_MOC_SRCS ${pokebattle_MOC_HEADERS})
+SET(pokebattle_HEADERS
+ ${pokebattle_MOC_HEADERS}
+ ActionQueue.h
+)
+SET(pokebattle_DEVEL
+ ${pokebattle_HEADERS}
+)
+SET(pokebattle_SRCS
+ Arena.cpp
+ ATBArena.cpp
+ ATBTimer.cpp
+ Containment.cpp
+ Ghost.cpp
+ Player.cpp
+ Team.cpp
+ TeamMember.cpp
+ TurnArena.cpp
+)
+
+ADD_LIBRARY(pokebattle
+ ${pokebattle_SRCS}
+ ${pokebattle_MOC_SRCS}
+)
+SET_TARGET_PROPERTIES(pokebattle
+ PROPERTIES
+ VERSION ${POKEGEN_VERSION}
+ SOVERSION ${POKEGEN_SOVERSION}
+ LINK_INTERFACE_LIBRARIES ""
+)
+TARGET_LINK_LIBRARIES(pokebattle
+ ${QT_QTCORE_LIBRARY}
+ ${QT_QTGUI_LIBRARY}
+ ${KDE4_KROSSCORE_LIBRARY}
+ pokemod
+ pokescripting
+)
+
+INSTALL(
+ TARGETS pokebattle
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}
+ COMPONENT runtime
+)
+
+INSTALL(
+ FILES ${pokebattle_DEVEL}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${CMAKE_PROJECT_NAME}/${PROJECT_NAME}
+ COMPONENT development
+)
diff --git a/sigbattle/Containment.cpp b/sigbattle/Containment.cpp
new file mode 100644
index 00000000..7dd31002
--- /dev/null
+++ b/sigbattle/Containment.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "Containment.h"
+
+Pokebattle::Containment::Containment(QObject* parent) :
+ QObject(parent)
+{
+}
+
+QList<Pokebattle::TeamMember*> Pokebattle::Containment::members() const
+{
+ return m_members;
+}
+
+Pokescripting::PokemodWrapper* Pokebattle::Containment::pokemod() const
+{
+ // TODO: return PokemodWrapper
+}
diff --git a/sigbattle/Containment.h b/sigbattle/Containment.h
new file mode 100644
index 00000000..e19061e9
--- /dev/null
+++ b/sigbattle/Containment.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_CONTAINMENT__
+#define __POKEBATTLE_CONTAINMENT__
+
+// Pokebattle includes
+#include "Global.h"
+
+// Qt includes
+#include <QtCore/QMetaType>
+#include <QtCore/QObject>
+
+// Forward declarations
+namespace Pokescripting
+{
+class PokemodWrapper;
+}
+
+namespace Pokebattle
+{
+class TeamMember;
+
+class POKEBATTLE_EXPORT Containment : public QObject
+{
+ Q_OBJECT
+
+ public:
+ Containment(QObject* parent);
+
+ QList<TeamMember*> members() const;
+
+ virtual bool isMutable() const = 0;
+
+ Pokescripting::PokemodWrapper* pokemod() const;
+ signals:
+ public slots:
+ protected slots:
+ protected:
+ QList<TeamMember*> m_members;
+};
+}
+Q_DECLARE_METATYPE(Pokebattle::Containment*)
+
+#endif
diff --git a/sigbattle/Ghost.cpp b/sigbattle/Ghost.cpp
new file mode 100644
index 00000000..4750636a
--- /dev/null
+++ b/sigbattle/Ghost.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "Ghost.h"
+
+// Ghost(const PokeMod::Pokemod& par, const unsigned s, const unsigned l, const unsigned t) :
+// Pokemon(par, s, l),
+// teamSize(t),
+// unknownMoves(par->GetMaxMoves())
+// {
+// for (unsigned i = 0; i < PokeMod::ST_End_GSC; ++i)
+// {
+// dv[i] = 0;
+// statExp[i] = 0;
+// minStats[i] = GetStat(i);
+// dv[i] = pokemod->GetMaxDV();
+// statExp[i] = 65535;
+// maxStats[i] = GetStat(i);
+// }
+// Species* pkmn = pokemod->GetSpeciesByID(s);
+// if (pkmn->GetNumAbilities() == 1)
+// FeedAbility(pkmn->GetAbility(0));
+// }
+//
+// void FeedAttack(const unsigned actualDamage, const unsigned stat, const unsigned otherLevel, const unsigned power, const bool isAttacker)
+// {
+//
+// }
+//
+// void FeedItem(const unsigned i)
+// {
+// items.append(i);
+// }
+//
+// void FeedMove(const unsigned m)
+// {
+// if (!moves.contains(m))
+// {
+// moves.insert(m);
+// --unknownMoves;
+// moveChances[m] = UINT_MAX;
+// for (QMutableMapIterator<unsigned, unsigned> i(moveChances); i.hasNext(); i.next())
+// {
+// if (i.value() != UINT_MAX)
+// {
+// i.value() *= unknownMoves;
+// i.value() /= (unknownMoves + 1);
+// if (!i.value())
+// moveChances.erase(i);
+// }
+// }
+// for (QListIterator<MoveCombo> i(moveCombos); i.hasNext(); i.next())
+// {
+// if (i.prereqs.intersect(moves).size() && !moves.contains(i.move))
+// moves[i.move] *= i.chance;
+// }
+// }
+// }
+//
+// void FeedMoveChance(const unsigned m, const unsigned weight)
+// {
+// moveChances[m] = weight;
+// }
+//
+// void FeedAbility(const unsigned a)
+// {
+// ability = a;
+// }
+//
+// void UpdateHP()
+// {
+// curHP = hpPercent * maxStats[PokeMod::ST_HP];
+// }
+//
+// void SetHP(const Frac p)
+// {
+// hpPercent = p;
+// UpdateHP();
+// }
diff --git a/sigbattle/Ghost.h b/sigbattle/Ghost.h
new file mode 100644
index 00000000..325f7108
--- /dev/null
+++ b/sigbattle/Ghost.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_GHOST__
+#define __POKEBATTLE_GHOST__
+
+// Pokebattle includes
+#include "TeamMember.h"
+
+namespace Pokebattle
+{
+class POKEBATTLE_EXPORT Ghost : public TeamMember
+{
+ Q_OBJECT
+
+// public:
+// Ghost(const PokeMod::Pokemod& par, const unsigned s, const unsigned l);
+//
+// void FeedAttack(const unsigned actualDamage, const unsigned stat, const unsigned otherLevel, const unsigned power, const bool isAttacker);
+// void FeedItem(const unsigned i);
+// void FeedMove(const unsigned m);
+// void FeedMoveChance(const unsigned m, const unsigned weight);
+// void FeedMoveCombo(const MoveCombo m);
+// void FeedAbility(const unsigned a);
+//
+// void UpdateHP();
+// void SetHP(const Frac p);
+// private:
+// struct MoveCombo
+// {
+// public:
+// MoveCombo(const QSet<unsigned> p, const unsigned m, const unsigned c) :
+// prereqs(p),
+// move(m),
+// chance(c)
+// {
+// }
+// QSet<unsigned> prereqs;
+// unsigned move;
+// const unsigned chance;
+// };
+//
+// unsigned minStats[PokeMod::ST_End_GSC];
+// unsigned maxStats[PokeMod::ST_End_GSC];
+// QMap<unsigned, unsigned> moveChances;
+// QList<MoveCombo> moveCombos;
+// unsigned unknownMoves;
+};
+}
+
+#endif
diff --git a/sigbattle/GhostBot.h b/sigbattle/GhostBot.h
new file mode 100644
index 00000000..459f2ccf
--- /dev/null
+++ b/sigbattle/GhostBot.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_GHOSTBOT__
+#define __POKEBATTLE_GHOSTBOT__
+
+// Pokebattle includes
+#include "Player.h"
+
+namespace Pokebattle
+{
+class POKEBATTLE_EXPORT GhostBot : public Player
+{
+ Q_OBJECT
+};
+}
+
+#endif
diff --git a/sigbattle/Global.h b/sigbattle/Global.h
new file mode 100644
index 00000000..713d8c9d
--- /dev/null
+++ b/sigbattle/Global.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_GLOBAL__
+#define __POKEBATTLE_GLOBAL__
+
+// KDE includes
+#include <kdemacros.h>
+
+#ifndef POKEBATTLE_EXPORT
+# ifdef MAKE_POKEBATTLE_LIB
+ /* We are building this library */
+# define POKEBATTLE_EXPORT KDE_EXPORT
+# else
+ /* We are using this library */
+# define POKEBATTLE_EXPORT KDE_IMPORT
+# endif
+#endif
+
+# ifndef POKEBATTLE_EXPORT_DEPRECATED
+# define POKEBATTLE_EXPORT_DEPRECATED KDE_DEPRECATED POKEBATTLE_EXPORT
+# endif
+
+#endif
diff --git a/sigbattle/Player.cpp b/sigbattle/Player.cpp
new file mode 100644
index 00000000..13e6076a
--- /dev/null
+++ b/sigbattle/Player.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "Player.h"
+
+Pokebattle::Player::Player(QObject* parent) :
+ Team(parent),
+ m_arena(NULL)
+{
+}
+
+void Pokebattle::Player::enterArena(Arena* arena)
+{
+ // TODO: Get a list of the active members
+ // TODO: Let them know that they are active
+}
+
+QList<Pokebattle::TeamMember*> Pokebattle::Player::active()
+{
+ // TODO: return active members
+}
+
+void Pokebattle::Player::exitArena()
+{
+ // TODO: Tell all active members that they can leave now
+}
diff --git a/sigbattle/Player.h b/sigbattle/Player.h
new file mode 100644
index 00000000..04b3d872
--- /dev/null
+++ b/sigbattle/Player.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_PLAYER__
+#define __POKEBATTLE_PLAYER__
+
+// Pokebattle includes
+#include "Global.h"
+#include "Team.h"
+#include "TeamMember.h"
+
+// Qt includes
+#include <QtCore/QObject>
+
+// Forward declarations
+namespace Pokemod
+{
+class Pokemod;
+}
+
+namespace Pokebattle
+{
+class Team;
+
+class POKEBATTLE_EXPORT Player : public Team
+{
+ Q_OBJECT
+
+ public:
+ Player(QObject* parent);
+
+ void enterArena(Arena* arena);
+
+ QList<TeamMember*> active();
+
+ const Pokemod::Pokemod* pokemod() const;
+ signals:
+ public slots:
+ void exitArena();
+
+ virtual TeamMember::Action requestAction(const TeamMember* teamMember) const = 0;
+ protected slots:
+ protected:
+ Arena* m_arena;
+};
+}
+Q_DECLARE_METATYPE(Pokebattle::Player*)
+
+#endif
diff --git a/sigbattle/TODO b/sigbattle/TODO
new file mode 100644
index 00000000..b9357c4b
--- /dev/null
+++ b/sigbattle/TODO
@@ -0,0 +1 @@
+Put global scripts into requesting for things
diff --git a/sigbattle/Team.cpp b/sigbattle/Team.cpp
new file mode 100644
index 00000000..22adea08
--- /dev/null
+++ b/sigbattle/Team.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "Team.h"
+
+Pokebattle::Team::Team(QObject* parent) :
+ Containment(parent)
+{
+ // TODO: construct
+}
+
+// Team::Team(const PokeMod::Pokemod& par) :
+// active(0),
+// parent(par)
+// {
+// }
+//
+// void Team::AddItem(const unsigned i, const unsigned amt)
+// {
+// if (amt)
+// items[i] = amt;
+// }
+//
+// void Team::UseItem(const unsigned i)
+// {
+// if (items.contains(i) && (items[i] != UINT_MAX))
+// {
+// --items[i];
+// if (!items[i])
+// items.remove(i);
+// }
+// }
+//
+// void Team::AddPokemon(Pokemon& p)
+// {
+// pokemon.append(&p);
+// }
+//
+// void Team::SwapPokemon(const unsigned a, const unsigned b)
+// {
+// if ((a < pokemon.size()) && (b < pokemon.size()))
+// {
+// Pokemon* p = pokemon[a];
+// pokemon[a] = pokemon[b];
+// pokemon[b] = p;
+// }
+// }
+//
+// bool Team::SetActivePokemon(const unsigned a)
+// {
+// if ((a < pokemon.size()) && pokemon[a]->CanFight())
+// active = a;
+// }
+
+bool Pokebattle::Team::isMutable() const
+{
+ return true;
+}
diff --git a/sigbattle/Team.h b/sigbattle/Team.h
new file mode 100644
index 00000000..63a85095
--- /dev/null
+++ b/sigbattle/Team.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_TEAM__
+#define __POKEBATTLE_TEAM__
+
+// Pokebattle includes
+#include "Containment.h"
+
+namespace Pokebattle
+{
+// Forward declarations
+class Arena;
+
+class POKEBATTLE_EXPORT Team : public Containment
+{
+ Q_OBJECT
+
+ public:
+ Team(QObject* parent);
+
+ virtual bool isMutable() const;
+ signals:
+ void teamKnockedOut();
+ public slots:
+ protected slots:
+ protected:
+ Arena* m_arena;
+};
+}
+Q_DECLARE_METATYPE(Pokebattle::Team*)
+
+#endif
diff --git a/sigbattle/TeamMember.cpp b/sigbattle/TeamMember.cpp
new file mode 100644
index 00000000..84727cb7
--- /dev/null
+++ b/sigbattle/TeamMember.cpp
@@ -0,0 +1,637 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "TeamMember.h"
+
+// Pokebattle includes
+#include "Arena.h"
+#include "Containment.h"
+#include "Player.h"
+
+// Pokescripting includes
+#include "../pokescripting/AbilityWrapper.h"
+#include "../pokescripting/ItemWrapper.h"
+#include "../pokescripting/MapTrainerTeamMemberWrapper.h"
+#include "../pokescripting/MoveWrapper.h"
+#include "../pokescripting/NatureWrapper.h"
+#include "../pokescripting/PokemodWrapper.h"
+#include "../pokescripting/RulesWrapper.h"
+#include "../pokescripting/StatusWrapper.h"
+#include "../pokescripting/SpeciesWrapper.h"
+#include "../pokescripting/SpeciesAbilityWrapper.h"
+#include "../pokescripting/SpeciesItemWrapper.h"
+#include "../pokescripting/SpeciesMoveWrapper.h"
+
+// Pokemod includes
+#include "../pokemod/Hat.h"
+
+// Qt includes
+#include <QtCore/QUuid>
+
+// KDE includes
+#include <kross/core/action.h>
+#include <kross/core/actioncollection.h>
+#include <kross/core/manager.h>
+
+// C includes
+#include <cmath>
+
+// TODO: Current HP
+// TODO: Script cleanup (battle)
+
+int Pokebattle::actionPriority(const TeamMember* teamMember, const TeamMember::Action& action)
+{
+ int priority = INT_MAX;
+ switch (action.first)
+ {
+ case TeamMember::Attack:
+ priority = teamMember->pokemod()->move(action.second.first.toString())->priority();
+ break;
+ case TeamMember::Item:
+ priority = INT_MIN / 3;
+ break;
+ case TeamMember::Switch:
+ priority = INT_MIN / 2;
+ break;
+ case TeamMember::Run:
+ priority = INT_MIN;
+ break;
+ case TeamMember::Skip:
+ priority = INT_MAX - 2;
+ break;
+ case TeamMember::Timeout:
+ priority = INT_MAX;
+ break;
+ case TeamMember::Invalid:
+ priority = INT_MAX - 1;
+ break;
+ }
+ return priority;
+}
+
+Pokebattle::TeamMember::TeamMember(const int speciesId, const QString& name, const int level, Containment* containment, const bool suppressItems) :
+ Pokescripting::Config(containment),
+ m_containment(containment),
+ m_id(QUuid::createUuid())
+{
+ makeConnections();
+ setSpecies(pokemod()->species(speciesId));
+ if (name.isEmpty())
+ setName(m_species->name());
+ else
+ setName(name);
+ setLevel(level);
+ if (!suppressItems)
+ initItems();
+ initAbilities();
+ initMoves();
+ initNatures();
+ initStats();
+ if (m_species->genderFactor() <= 1)
+ m_gender = (m_species->genderFactor().poll() ? Male : Female);
+ else
+ m_gender = Genderless;
+ for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
+ m_statExp[i] = 0;
+ if (m_containment->isMutable())
+ {
+ const Pokemod::Script script = m_species->evolution();
+ Kross::Action* evolution = new Kross::Action(Kross::Manager::self().actionCollection()->collection("evolutions"), QString("evolution-%1").arg(QUuid::createUuid().toString()));
+ evolution->setInterpreter(script.interpreter());
+ evolution->setCode(script.script().toUtf8());
+ evolution->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ evolution->trigger();
+ }
+ m_currentHp = statValue(Pokemod::ST_HP);
+}
+
+Pokebattle::TeamMember::TeamMember(Pokescripting::MapTrainerTeamMemberWrapper* teamMember, Containment* containment) :
+ Pokescripting::Config(containment),
+ m_containment(containment),
+ m_id(QUuid::createUuid())
+{
+ makeConnections();
+ setSpecies(teamMember->species());
+ setName(m_species->name());
+ setLevel(teamMember->level());
+ m_items = teamMember->items();
+ initAbilities(teamMember->abilities());
+ initMoves(teamMember->moves());
+ initNatures(teamMember->natures());
+ initStats();
+ if (m_species->genderFactor() <= 1)
+ m_gender = (m_species->genderFactor().poll() ? Male : Female);
+ else
+ m_gender = Genderless;
+ for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
+ m_statExp[i] = 0;
+ m_currentHp = statValue(Pokemod::ST_HP);
+}
+
+QUuid Pokebattle::TeamMember::id() const
+{
+ return m_id;
+}
+
+QString Pokebattle::TeamMember::name() const
+{
+ if (value("name").canConvert<QString>())
+ return value("name").toString();
+ return m_name;
+}
+
+long long Pokebattle::TeamMember::currentHp() const
+{
+ return m_currentHp;
+}
+
+Pokescripting::SpeciesWrapper* Pokebattle::TeamMember::species() const
+{
+ if (value("species").canConvert<Pokescripting::SpeciesWrapper*>())
+ return value("species").value<Pokescripting::SpeciesWrapper*>();
+ return m_species;
+}
+
+int Pokebattle::TeamMember::level() const
+{
+ return m_level;
+}
+
+Pokebattle::TeamMember::Gender Pokebattle::TeamMember::gender() const
+{
+ if (value("gender").canConvert<Gender>())
+ return value("gender").value<Gender>();
+ return m_gender;
+}
+
+long long Pokebattle::TeamMember::levelExperience() const
+{
+ if (value("levelExperience").canConvert<long long>())
+ return value("levelExperience").toLongLong();
+ return m_levelExp;
+}
+
+int Pokebattle::TeamMember::baseStat(const Pokemod::Stat stat) const
+{
+ if (value("overrideBaseStats").canConvert<bool>() && value("overrideBaseStats").toBool())
+ return species()->baseStat(stat);
+ return m_species->baseStat(stat);
+}
+
+long long Pokebattle::TeamMember::statExperience(const Pokemod::Stat stat) const
+{
+ const QString valueName = QString("statExperience-%1").arg((pokemod()->rules()->specialSplit() ? Pokemod::StatGSCStr : Pokemod::StatRBYStr)[stat]);
+ if (value(valueName).canConvert<long long>())
+ return value(valueName).toLongLong();
+ return m_statExp[stat];
+}
+
+int Pokebattle::TeamMember::dv(const Pokemod::Stat stat) const
+{
+ const QString valueName = QString("dv-%1").arg((pokemod()->rules()->specialSplit() ? Pokemod::StatGSCStr : Pokemod::StatRBYStr)[stat]);
+ if (value(valueName).canConvert<int>())
+ {
+ const int dv = value(valueName).toInt();
+ if (dv < (pokemod()->rules()->specialDVSplit() ? 32 : 16))
+ return dv;
+ }
+ return m_dv[stat];
+}
+
+long long Pokebattle::TeamMember::statValue(const Pokemod::Stat stat, const long long exp) const
+{
+ long long statValue;
+ if (exp < 0)
+ statValue = statExperience(stat);
+ else
+ statValue = exp;
+ if (!pokemod()->rules()->effortValuesAllowed() && statValue)
+ statValue = sqrt(statValue - 1) + 1;
+ statValue >>= 2;
+ statValue += baseStat(stat) << 1;
+ if (pokemod()->rules()->specialDVSplit())
+ {
+ if (stat == Pokemod::ST_SpecialDefense)
+ statValue += dv(Pokemod::ST_Special) << 1;
+ else
+ statValue += dv(stat) << 1;
+ }
+ else
+ statValue += dv(stat);
+ statValue *= double(m_level) / pokemod()->rules()->maxLevel();
+ if (stat == Pokemod::ST_HP)
+ statValue += 10 + m_level;
+ else
+ {
+ statValue += 5;
+ Pokemod::Fraction multiplier;
+ foreach (Pokescripting::NatureWrapper* nature, m_natures)
+ multiplier *= nature->stat(stat);
+ statValue *= multiplier;
+ }
+ return statValue;
+}
+
+long long Pokebattle::TeamMember::calcExp(int level) const
+{
+ if (level < 0)
+ level = m_level;
+ const long long square = level * level;
+ const long long cube = square * level;
+ switch (m_species->growth())
+ {
+ case Pokemod::Species::Fluctuating:
+ if (level <= 15)
+ return cube * ((24 + (level + 1) / 3) / 50.0);
+ else if (level <= 35)
+ return cube * ((14 + level) / 50.0);
+ else if (level <= 100)
+ return cube * ((32 + (level / 2)) / 50.0);
+ // TODO: better way for further growth?
+ else if (level <= 102)
+ return cube * (23 + level) / 75;
+ else
+ return 5 * cube / 3;
+ case Pokemod::Species::Fading:
+ return 6 * cube / 5 - 15 * square + 100 * level - 140;
+ case Pokemod::Species::Slow:
+ return 5 * cube / 4;
+ case Pokemod::Species::Normal:
+ return cube;
+ case Pokemod::Species::Fast:
+ return 4 * cube / 5;
+ case Pokemod::Species::Erratic:
+ {
+ const double p[] = {0.000, 0.008, 0.014};
+ if (level <= 50)
+ return cube * ((100 - level) / 50.0);
+ else if (level <= 68)
+ return cube * ((150 - level) / 100.0);
+ else if (level <= 98)
+ return cube * (1.274 - (level / 3) / 50.0 - p[level % 3]);
+ else if (level <= 100)
+ return cube * ((160 - level) / 100.0);
+ // TODO: better way for further growth?
+ else
+ return 3 * cube / 5;
+ }
+ default:
+ break;
+ }
+ return -1;
+}
+
+bool Pokebattle::TeamMember::canLearnMove(Pokescripting::MoveWrapper* move) const
+{
+ for (int i = 0; i < m_species->moveCount(); ++i)
+ {
+ if (move->id() == m_species->move(i)->move()->id())
+ return true;
+ }
+ return false;
+}
+
+void Pokebattle::TeamMember::boostLevels(const int levels)
+{
+ if ((m_level + levels) < pokemod()->rules()->maxLevel())
+ {
+ for (int i = 0; i < levels; ++i)
+ setLevel(m_level + 1);
+ }
+}
+
+void Pokebattle::TeamMember::evolveInto(Pokescripting::SpeciesWrapper* newSpecies)
+{
+ emit(evolveStart());
+ int oldStats[Pokemod::ST_End_GSC] = {};
+ int newStats[Pokemod::ST_End_GSC] = {};
+ oldStats[Pokemod::ST_Attack] = statValue(Pokemod::ST_Attack);
+ oldStats[Pokemod::ST_Defense] = statValue(Pokemod::ST_Defense);
+ oldStats[Pokemod::ST_Speed] = statValue(Pokemod::ST_Speed);
+ if (pokemod()->rules()->specialSplit())
+ {
+ oldStats[Pokemod::ST_SpecialAttack] = statValue(Pokemod::ST_SpecialAttack);
+ oldStats[Pokemod::ST_SpecialDefense] = statValue(Pokemod::ST_SpecialDefense);
+ }
+ else
+ oldStats[Pokemod::ST_Special] = statValue(Pokemod::ST_Special);
+ setSpecies(newSpecies);
+ newStats[Pokemod::ST_Attack] = statValue(Pokemod::ST_Attack);
+ newStats[Pokemod::ST_Defense] = statValue(Pokemod::ST_Defense);
+ newStats[Pokemod::ST_Speed] = statValue(Pokemod::ST_Speed);
+ if (pokemod()->rules()->specialSplit())
+ {
+ newStats[Pokemod::ST_SpecialAttack] = statValue(Pokemod::ST_SpecialAttack);
+ newStats[Pokemod::ST_SpecialDefense] = statValue(Pokemod::ST_SpecialDefense);
+ }
+ else
+ newStats[Pokemod::ST_Special] = statValue(Pokemod::ST_Special);
+ if (oldStats[Pokemod::ST_Attack] != newStats[Pokemod::ST_Attack])
+ emit(statChanged(Pokemod::ST_Attack, newStats[Pokemod::ST_Attack]));
+ if (oldStats[Pokemod::ST_Defense] != newStats[Pokemod::ST_Defense])
+ emit(statChanged(Pokemod::ST_Defense, newStats[Pokemod::ST_Defense]));
+ if (oldStats[Pokemod::ST_Speed] != newStats[Pokemod::ST_Speed])
+ emit(statChanged(Pokemod::ST_Speed, newStats[Pokemod::ST_Speed]));
+ if (pokemod()->rules()->specialSplit())
+ {
+ if (oldStats[Pokemod::ST_SpecialAttack] != newStats[Pokemod::ST_SpecialAttack])
+ emit(statChanged(Pokemod::ST_SpecialAttack, newStats[Pokemod::ST_SpecialAttack]));
+ if (oldStats[Pokemod::ST_SpecialDefense] != newStats[Pokemod::ST_SpecialDefense])
+ emit(statChanged(Pokemod::ST_SpecialDefense, newStats[Pokemod::ST_SpecialDefense]));
+ }
+ else
+ {
+ if (oldStats[Pokemod::ST_Special] != newStats[Pokemod::ST_Special])
+ emit(statChanged(Pokemod::ST_Special, newStats[Pokemod::ST_Special]));
+ }
+ emit(evolveEnd());
+}
+
+void Pokebattle::TeamMember::setName(const QString& name)
+{
+ if (m_name != name)
+ {
+ const QString oldName = m_name;
+ m_name = name;
+ emit(nameChanged(oldName, m_name));
+ }
+}
+
+void Pokebattle::TeamMember::cureStatus(Pokescripting::StatusWrapper* status)
+{
+ if (m_status.contains(status))
+ {
+ QList<Kross::Action*> actions = m_status.values(status);
+ foreach (Kross::Action* action, actions)
+ delete action;
+ m_status.remove(status);
+ emit(statusCured(status));
+ }
+}
+
+void Pokebattle::TeamMember::giveStatus(Pokescripting::StatusWrapper* status)
+{
+ Q_ASSERT(pokemod()->statusIndex(status) != INT_MAX);
+ if (!m_status.contains(status))
+ {
+ const Pokemod::Script script = status->worldScript();
+ Kross::Action* statusAction = new Kross::Action(Kross::Manager::self().actionCollection()->collection("status"), QString("status-%1").arg(QUuid::createUuid().toString()));
+ statusAction->setInterpreter(script.interpreter());
+ statusAction->setCode(script.script().toUtf8());
+ statusAction->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ statusAction->trigger();
+ m_status.insert(status, statusAction);
+ emit(statusInflicted(status));
+ }
+}
+
+void Pokebattle::TeamMember::giveLevelExp(const int exp)
+{
+ if (m_level == pokemod()->rules()->maxLevel())
+ return;
+ const int expNeeded = calcExp(m_level + 1) - calcExp();
+ if (exp < expNeeded)
+ {
+ m_levelExp += exp;
+ emit(expGained(exp));
+ }
+ else
+ {
+ setLevel(m_level + 1);
+ emit(expGained(expNeeded));
+ giveLevelExp(exp - expNeeded);
+ }
+}
+
+void Pokebattle::TeamMember::giveStatExp(const Pokemod::Stat stat, const int exp)
+{
+ Q_ASSERT(stat < (pokemod()->rules()->specialSplit() ? Pokemod::ST_End_GSC : Pokemod::ST_End_RBY));
+ const int oldStat = statValue(stat);
+ int expToGive = exp;
+ if (pokemod()->rules()->effortValuesAllowed())
+ {
+ int totalEV = 0;
+ for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
+ totalEV += m_statExp[i];
+ while (expToGive && (totalEV < pokemod()->rules()->maxTotalEV()) && (m_statExp[stat] < pokemod()->rules()->maxEVPerStat()))
+ {
+ --expToGive;
+ ++totalEV;
+ ++m_statExp[stat];
+ }
+ }
+ else
+ {
+ while (expToGive && (m_statExp[stat] < INT_MAX))
+ {
+ --expToGive;
+ ++m_statExp[stat];
+ }
+ }
+ const int newStat = statValue(stat);
+ if (oldStat != newStat)
+ emit(statChanged(stat, newStat));
+}
+
+void Pokebattle::TeamMember::takeItem(Pokescripting::ItemWrapper* item)
+{
+ if (m_items.contains(item))
+ {
+ m_items.removeAt(m_items.indexOf(item));
+ emit(itemTaken(item));
+ }
+}
+
+void Pokebattle::TeamMember::giveItem(Pokescripting::ItemWrapper* item)
+{
+ if (m_items.size() < pokemod()->rules()->maxHeldItems())
+ {
+ m_items.append(item);
+ emit(itemGiven(item));
+ }
+}
+
+void Pokebattle::TeamMember::forgetMove(Pokescripting::MoveWrapper* move)
+{
+ if (m_moves.contains(move))
+ {
+ m_moves.removeAll(move);
+ emit(moveForgotten(move));
+ }
+}
+
+void Pokebattle::TeamMember::teachMove(Pokescripting::MoveWrapper* move)
+{
+ if (canLearnMove(move))
+ {
+ if (m_moves.size() < pokemod()->rules()->maxMoves())
+ {
+ m_moves.append(move);
+ emit(moveLearned(move));
+ }
+ emit(movesFull(move));
+ }
+ emit(unlearnableMove(move));
+}
+
+Pokebattle::TeamMember::Action Pokebattle::TeamMember::requestAction() const
+{
+ Player* player = qobject_cast<Player*>(m_containment);
+ if (player)
+ return player->requestAction(this);
+ return Action(Invalid, ActionData());
+}
+
+void Pokebattle::TeamMember::makeActive(Arena* arena)
+{
+ QList<Pokescripting::StatusWrapper*> statuses = m_status.uniqueKeys();
+ foreach (Pokescripting::StatusWrapper* status, statuses)
+ {
+ const Pokemod::Script script = status->battleScript();
+ Kross::Action* statusScript = new Kross::Action(Kross::Manager::self().actionCollection()->collection("status"), QString("status-%1").arg(QUuid::createUuid().toString()));
+ statusScript->setInterpreter(script.interpreter());
+ statusScript->setCode(script.script().toUtf8());
+ statusScript->addObject(arena, "arena", Kross::ChildrenInterface::AutoConnectSignals);
+ statusScript->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ statusScript->trigger();
+ m_statusBattleScripts.append(statusScript);
+ }
+ QList<Pokescripting::AbilityWrapper*> abilities = m_abilities.keys();
+ foreach (Pokescripting::AbilityWrapper* ability, abilities)
+ {
+ const Pokemod::Script script = ability->battleScript();
+ Kross::Action* abilityScript = new Kross::Action(Kross::Manager::self().actionCollection()->collection("ability"), QString("ability-%1").arg(QUuid::createUuid().toString()));
+ abilityScript->setInterpreter(script.interpreter());
+ abilityScript->setCode(script.script().toUtf8());
+ abilityScript->addObject(arena, "arena", Kross::ChildrenInterface::AutoConnectSignals);
+ abilityScript->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ abilityScript->trigger();
+ m_abilityBattleScripts.append(abilityScript);
+ }
+}
+
+void Pokebattle::TeamMember::writeBack()
+{
+ // TODO: write back all (applicable) differences between config and local storage
+}
+
+Pokescripting::PokemodWrapper* Pokebattle::TeamMember::pokemod() const
+{
+ return m_containment->pokemod();
+}
+
+void Pokebattle::TeamMember::setSpecies(Pokescripting::SpeciesWrapper* species)
+{
+ m_species = species;
+ emit(speciesChanged(m_species));
+}
+
+void Pokebattle::TeamMember::setLevel(const int level)
+{
+ emit(levelAboutToGrow());
+ m_level = level;
+ emit(levelGrown(level));
+ m_levelExp = calcExp();
+}
+
+void Pokebattle::TeamMember::levelGrown()
+{
+ for (int i = 0; i < m_species->moveCount(); ++i)
+ {
+ Pokescripting::SpeciesMoveWrapper* move = m_species->move(i);
+ if (move->level() == m_level)
+ teachMove(move->move());
+ }
+}
+
+void Pokebattle::TeamMember::makeConnections()
+{
+ // TODO: make connections that are necessary (watching Config changes mainly)
+}
+
+void Pokebattle::TeamMember::initAbility(Pokescripting::AbilityWrapper* ability)
+{
+ const Pokemod::Script script = ability->battleScript();
+ Kross::Action* abilityScript = new Kross::Action(Kross::Manager::self().actionCollection()->collection("ability"), QString("ability-%1").arg(QUuid::createUuid().toString()));
+ abilityScript->setInterpreter(script.interpreter());
+ abilityScript->setCode(script.script().toUtf8());
+ abilityScript->addObject(this, "owner", Kross::ChildrenInterface::AutoConnectSignals);
+ abilityScript->trigger();
+ m_abilities[ability] = abilityScript;
+}
+
+void Pokebattle::TeamMember::initItems()
+{
+ Pokemod::Hat<Pokescripting::ItemWrapper*> hat = m_species->itemHat();
+ for (int i = 0; i < pokemod()->rules()->maxHeldItems(); ++i)
+ {
+ if (m_species->itemChance().poll())
+ m_items.append(hat.pick());
+ }
+}
+
+void Pokebattle::TeamMember::initAbilities(const QList<Pokescripting::AbilityWrapper*>& initial)
+{
+ foreach (Pokescripting::AbilityWrapper* ability, initial)
+ initAbility(ability);
+ Pokemod::Hat<Pokescripting::AbilityWrapper*> hat = m_species->abilityHat();
+ while (m_abilities.size() < pokemod()->rules()->maxAbilities())
+ {
+ Pokescripting::AbilityWrapper* ability = hat.takeAndClear();
+ if (!m_abilities.contains(ability))
+ initAbility(ability);
+ }
+}
+
+void Pokebattle::TeamMember::initMoves(const QList<Pokescripting::MoveWrapper*>& initial)
+{
+ m_moves = initial;
+ for (int i = 0; (i < m_species->moveCount()) && (m_moves.size() < pokemod()->rules()->maxMoves()); ++i)
+ {
+ Pokescripting::SpeciesMoveWrapper* move = m_species->move(i);
+ if (!m_moves.contains(move->move()) && (((move->level() < m_level) && move->level()) || (!m_containment->isMutable() && (move->wild() < m_level))))
+ m_moves.append(move->move());
+ }
+}
+
+void Pokebattle::TeamMember::initNatures(const QList<Pokescripting::NatureWrapper*>& initial)
+{
+ m_natures = initial;
+ Pokemod::Hat<Pokescripting::NatureWrapper*> hat = pokemod()->natureHat();
+ while (m_natures.size() < pokemod()->rules()->maxNatures())
+ {
+ Pokescripting::NatureWrapper* nature = hat.takeAndClear();
+ if (!m_natures.contains(nature))
+ m_natures.append(nature);
+ }
+}
+
+void Pokebattle::TeamMember::initStats()
+{
+ if (pokemod()->rules()->specialDVSplit())
+ {
+ for (int i = 0; i < Pokemod::ST_End_GSC; ++i)
+ m_dv[i] = qrand() & 31;
+ }
+ else
+ {
+ for (int i = Pokemod::ST_No_HP_Start; i < Pokemod::ST_End_RBY; ++i)
+ m_dv[i] = qrand() & 15;
+ m_dv[Pokemod::ST_HP] = ((m_dv[Pokemod::ST_Attack] & 1) << 3) + ((m_dv[Pokemod::ST_Defense] & 1) << 2) + ((m_dv[Pokemod::ST_Speed] & 1) << 1) + (m_dv[Pokemod::ST_Special] & 1);
+ }
+}
diff --git a/sigbattle/TeamMember.h b/sigbattle/TeamMember.h
new file mode 100644
index 00000000..db61571a
--- /dev/null
+++ b/sigbattle/TeamMember.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2007-2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_TEAMMEMBER__
+#define __POKEBATTLE_TEAMMEMBER__
+
+// Pokebattle includes
+#include "Global.h"
+
+// Pokescripting includes
+#include "../pokescripting/Config.h"
+
+// Pokemod includes
+#include "../pokemod/Global.h"
+
+// Qt includes
+#include <QtCore/QFuture>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QMultiMap>
+#include <QtCore/QObject>
+#include <QtCore/QPair>
+#include <QtCore/QString>
+#include <QtCore/QUuid>
+
+// Forward declarations
+namespace Pokescripting
+{
+class AbilityWrapper;
+class ItemWrapper;
+class MoveWrapper;
+class NatureWrapper;
+class MapTrainerTeamMemberWrapper;
+class PokemodWrapper;
+class SpeciesWrapper;
+class StatusWrapper;
+}
+namespace Kross
+{
+class Action;
+}
+
+namespace Pokebattle
+{
+class Arena;
+class Containment;
+
+class POKEBATTLE_EXPORT TeamMember : public Pokescripting::Config
+{
+ Q_OBJECT
+
+ public:
+ enum Gender
+ {
+ Male = 0,
+ Female = 1,
+ Genderless = 2
+ };
+
+ enum ActionType
+ {
+ Attack = 0,
+ Item = 1,
+ Switch = 2,
+ Run = 3,
+ Skip = 4,
+ Timeout = 5,
+ Invalid = 6
+ };
+
+ typedef QList<QUuid> Targets;
+ typedef QPair<QVariant, Targets> ActionData;
+ typedef QPair<ActionType, ActionData> Action;
+ typedef QPair<TeamMember*, QFuture<TeamMember::Action> > RequestedAction;
+
+ TeamMember(const int speciesId, const QString& name, const int level, Containment* containment, const bool suppressItems = false);
+ TeamMember(Pokescripting::MapTrainerTeamMemberWrapper* teamMember, Containment* containment);
+
+ QUuid id() const;
+
+ QString name() const;
+ long long currentHp() const;
+ Pokescripting::SpeciesWrapper* species() const;
+ int level() const;
+ Gender gender() const;
+ long long levelExperience() const;
+ int baseStat(const Pokemod::Stat stat) const;
+ long long statExperience(const Pokemod::Stat stat) const;
+ int dv(const Pokemod::Stat stat) const;
+ long long statValue(const Pokemod::Stat stat, const long long exp = -1) const;
+ long long calcExp(int level = -1) const;
+
+ bool canLearnMove(Pokescripting::MoveWrapper* move) const;
+
+ Pokescripting::PokemodWrapper* pokemod() const;
+ signals:
+ void speciesChanged(Pokescripting::SpeciesWrapper* species);
+
+ void evolveStart();
+ void evolveEnd();
+
+ void nameChanged(const QString& oldName, const QString& newName);
+
+ void statusCured(Pokescripting::StatusWrapper* status);
+ void statusInflicted(Pokescripting::StatusWrapper* status);
+
+ void expGained(const int exp);
+ void levelAboutToGrow();
+ void levelGrown(const int newLevel);
+
+ void statChanged(const Pokemod::Stat stat, const int value);
+ void effortFull(const int stat);
+ void totalEffortFull();
+
+ void itemTaken(Pokescripting::ItemWrapper* item);
+ void itemGiven(Pokescripting::ItemWrapper* item);
+
+ void moveForgotten(Pokescripting::MoveWrapper* move);
+ void moveLearned(Pokescripting::MoveWrapper* move);
+ void movesFull(Pokescripting::MoveWrapper* move);
+ void unlearnableMove(Pokescripting::MoveWrapper* move);
+
+ void knockedOut();
+ public slots:
+ void boostLevels(const int levels);
+
+ void evolveInto(Pokescripting::SpeciesWrapper* newSpecies);
+
+ void setName(const QString& name);
+ void cureStatus(Pokescripting::StatusWrapper* status);
+ void giveStatus(Pokescripting::StatusWrapper* status);
+ void giveLevelExp(const int exp);
+ void giveStatExp(const Pokemod::Stat stat, const int exp);
+ void takeItem(Pokescripting::ItemWrapper* item);
+ void giveItem(Pokescripting::ItemWrapper* item);
+ void forgetMove(Pokescripting::MoveWrapper* move);
+ void teachMove(Pokescripting::MoveWrapper* move);
+
+ Action requestAction() const;
+
+ void makeActive(Arena* arena);
+
+ virtual void writeBack();
+ protected slots:
+ void setSpecies(Pokescripting::SpeciesWrapper* species);
+ void setLevel(const int level);
+ private slots:
+ void levelGrown();
+ protected:
+ Containment* m_containment;
+
+ const QUuid m_id;
+
+ QString m_name;
+ long long m_currentHp;
+ Pokescripting::SpeciesWrapper* m_species;
+ Gender m_gender;
+ long long m_levelExp;
+ int m_level;
+ long long m_statExp[Pokemod::ST_End_GSC];
+ int m_dv[Pokemod::ST_End_GSC];
+ QMultiMap<Pokescripting::StatusWrapper*, Kross::Action*> m_status;
+ QMap<Pokescripting::AbilityWrapper*, Kross::Action*> m_abilities;
+ QList<Pokescripting::ItemWrapper*> m_items;
+ QList<Pokescripting::MoveWrapper*> m_moves;
+ QList<Pokescripting::NatureWrapper*> m_natures;
+
+ QList<Kross::Action*> m_abilityBattleScripts;
+ QList<Kross::Action*> m_statusBattleScripts;
+ private:
+ void makeConnections();
+
+ void initAbility(Pokescripting::AbilityWrapper* ability);
+
+ void initItems();
+ void initAbilities(const QList<Pokescripting::AbilityWrapper*>& initial = QList<Pokescripting::AbilityWrapper*>());
+ void initMoves(const QList<Pokescripting::MoveWrapper*>& initial = QList<Pokescripting::MoveWrapper*>());
+ void initNatures(const QList<Pokescripting::NatureWrapper*>& initial = QList<Pokescripting::NatureWrapper*>());
+ void initStats();
+};
+
+int actionPriority(const TeamMember* teamMember, const TeamMember::Action& action);
+
+}
+Q_DECLARE_METATYPE(Pokebattle::TeamMember*)
+Q_DECLARE_METATYPE(Pokebattle::TeamMember::Gender)
+Q_DECLARE_METATYPE(Pokebattle::TeamMember::ActionType)
+Q_DECLARE_METATYPE(Pokebattle::TeamMember::Targets)
+Q_DECLARE_METATYPE(Pokebattle::TeamMember::ActionData)
+Q_DECLARE_METATYPE(Pokebattle::TeamMember::Action)
+Q_DECLARE_METATYPE(Pokebattle::TeamMember::RequestedAction)
+
+#endif
diff --git a/sigbattle/TurnArena.cpp b/sigbattle/TurnArena.cpp
new file mode 100644
index 00000000..bf0bece8
--- /dev/null
+++ b/sigbattle/TurnArena.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Header include
+#include "TurnArena.h"
+
+// Pokemod includes
+#include "../pokemod/Fraction.h"
+
+// Qt includes
+#include <QtAlgorithms>
+#include <QtCore/QtConcurrentMap>
+#include <QtCore/QFuture>
+#include <QtCore/QTimer>
+
+bool Pokebattle::sortActions(const TeamMember::RequestedAction& reqAction1, const TeamMember::RequestedAction& reqAction2)
+{
+ TeamMember::Action action1 = reqAction1.second.isFinished() ? reqAction1.second : TeamMember::Action(TeamMember::Timeout, TeamMember::ActionData());
+ TeamMember::Action action2 = reqAction2.second.isFinished() ? reqAction2.second : TeamMember::Action(TeamMember::Timeout, TeamMember::ActionData());
+ const int priority1 = actionPriority(reqAction1.first, action1);
+ const int priority2 = actionPriority(reqAction1.first, action2);
+ if (priority1 < priority2)
+ return true;
+ else if (priority1 == priority2)
+ {
+ const int speed1 = reqAction1.first->statValue(Pokemod::ST_Speed);
+ const int speed2 = reqAction2.first->statValue(Pokemod::ST_Speed);
+ if (speed1 < speed2)
+ return true;
+ else if (speed1 == speed2)
+ return Pokemod::Fraction(1, 2).poll();
+ }
+ return false;
+}
+
+Pokebattle::TurnArena::TurnArena(QList<Player*> players, QObject* parent) :
+ Arena(players, parent),
+ m_watcher(new QFutureWatcher<TeamMember::RequestedAction>(this)),
+ m_timer(new QTimer(this))
+{
+ setupBattle();
+ m_timer->setSingleShot(true);
+ connect(m_timer, SIGNAL(timeout()), m_watcher, SLOT(cancel()));
+}
+
+void Pokebattle::TurnArena::processRound()
+{
+ emit(roundAboutToStart());
+ emit(roundStart());
+ QFuture<TeamMember::RequestedAction> reqActions = QtConcurrent::mapped(active(), &Pokebattle::requestDecision);
+ m_watcher->setFuture(reqActions);
+ m_timer->start(120000);
+ reqActions.waitForFinished();
+ m_timer->stop();
+ QList<TeamMember::RequestedAction> actions = reqActions.results();
+ qStableSort(actions.begin(), actions.end(), sortActions);
+ for (int i = 0; i < actions.size(); ++i)
+ {
+ for (int j = 0; j < i; ++j)
+ {
+
+ // TODO: Notify scripts of the moves before it and of its targets
+ }
+ }
+ // TODO: notify all attacks of what is going on in order (they can change priorities as needed)
+ qStableSort(actions.begin(), actions.end(), sortActions);
+ foreach (TeamMember::RequestedAction action, actions)
+ {
+ // TODO: Handle when the target switches or is knocked out
+ if (action.first->currentHp())
+ handleAction(action.first, action.second);
+ }
+ emit(roundAboutToEnd());
+ emit(roundEnd());
+ if (numActiveTeams() <= 1)
+ {
+ // TODO: End Round
+ }
+ else
+ processRound();
+}
+
+void Pokebattle::TurnArena::setupBattle()
+{
+ // TODO: setup everything for the arena to do with the turns
+ Arena::setupBattle();
+}
diff --git a/sigbattle/TurnArena.h b/sigbattle/TurnArena.h
new file mode 100644
index 00000000..636ae501
--- /dev/null
+++ b/sigbattle/TurnArena.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2008 Ben Boeckel <MathStuf@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __POKEBATTLE_TURNARENA__
+#define __POKEBATTLE_TURNARENA__
+
+// Pokebattle includes
+#include "Arena.h"
+#include "TeamMember.h"
+
+// Qt includes
+#include <QtCore/QFutureWatcher>
+
+// Forward declarations
+class QTimer;
+
+namespace Pokebattle
+{
+class POKEBATTLE_EXPORT TurnArena : public Arena
+{
+ Q_OBJECT
+
+ public:
+ TurnArena(QList<Player*> players, QObject* parent);
+ signals:
+ void roundAboutToStart();
+ void roundStart();
+ void roundAboutToEnd();
+ void roundEnd();
+ public slots:
+ protected slots:
+ void processRound();
+ protected:
+ void setupBattle();
+ private:
+ QFutureWatcher<TeamMember::RequestedAction>* m_watcher;
+ QTimer* m_timer;
+};
+
+bool sortActions(const TeamMember::RequestedAction& reqAction1, const TeamMember::RequestedAction& reqAction2);
+
+}
+Q_DECLARE_METATYPE(Pokebattle::TurnArena*)
+
+#endif