/* * Copyright 2007-2008 Ben Boeckel * * 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 . */ // Header include #include "Arena.h" // Sigbattle includes #include "Player.h" // Sigscript includes #include "../sigscript/ItemWrapper.h" #include "../sigscript/MoveWrapper.h" #include "../sigscript/SigmodWrapper.h" #include "../sigscript/SpeciesWrapper.h" // Sigmod includes // #include "../sigmod/Fraction.h" #include "../sigmod/Script.h" // KDE includes #include #include #include // Qt includes #include #include Sigbattle::TeamMember::RequestedAction Sigbattle::requestDecision(TeamMember* teamMember) { return TeamMember::RequestedAction(teamMember, QtConcurrent::run(decision, teamMember)); } Sigbattle::TeamMember::Action Sigbattle::decision(TeamMember* teamMember) { return teamMember->requestAction(); } Sigbattle::Arena::Arena(Sigscript::SigmodWrapper* sigmod, QList players, const bool isWild, QObject* parent) : Sigscript::Config(parent), m_sigmod(sigmod), m_isWild(isWild), m_isOver(false), 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); } Sigbattle::Arena::~Arena() { delete m_actions; } QList Sigbattle::Arena::active() const { QList active; foreach (Player* player, m_players) active += player->active(); return active; } int Sigbattle::Arena::numActiveTeams() const { int active = 0; foreach (Player* player, m_players) active += !player->active().isEmpty(); return active; } bool Sigbattle::Arena::isOver() const { return m_isOver; } Sigscript::SigmodWrapper* Sigbattle::Arena::sigmod() const { return m_sigmod; } void Sigbattle::Arena::registerScript(const Sigmod::Script& script) { if (!script.script().isEmpty()) { Kross::Action* action = new Kross::Action(m_actions, QUuid::createUuid().toString()); action->setInterpreter(script.interpreter()); action->setCode(script.script().toUtf8()); action->addObject(this, "arena"); action->trigger(); } } void Sigbattle::Arena::cleanUp() { emit(aboutToClearActions()); m_isOver = true; QList actions = m_actions->actions(); foreach (Kross::Action* action, actions) m_actions->removeAction(action); distributeWinnings(); foreach (Player* player, m_players) player->exitArena(); } void Sigbattle::Arena::handleAction(TeamMember* teamMember, TeamMember::Action action) { TeamMember::ActionData data = action.second; switch (action.first) { case TeamMember::Attack: { Sigscript::MoveWrapper* move = sigmod()->move(data.first.toInt()); if (move) { const Sigmod::Script script = move->battleScript(); if (!script.script().isEmpty()) { Kross::Action* kaction = new Kross::Action(m_actions, QUuid::createUuid().toString()); kaction->setInterpreter(script.interpreter()); kaction->setCode(script.script().toUtf8()); kaction->addObject(this, "arena"); kaction->addObject(teamMember, "user"); for (int i = 0; i < data.second.size(); ++i) kaction->addObject(findMember(data.second[i]), QString("target%1").arg(i)); kaction->trigger(); } } break; } case TeamMember::Item: { Sigscript::ItemWrapper* item = sigmod()->item(data.first.toInt()); if (item) { const Sigmod::Script script = item->script(); if (!script.script().isEmpty()) { Kross::Action* kaction = new Kross::Action(m_actions, QUuid::createUuid().toString()); kaction->setInterpreter(script.interpreter()); kaction->setCode(script.script().toUtf8()); kaction->addObject(this, "arena"); kaction->addObject(findMember(data.second[0]), "target"); kaction->trigger(); } } break; } case TeamMember::Switch: { Player* player = qobject_cast(teamMember->containment()); if (player) player->switchOut(teamMember, player->findMember(data.second[0])); break; } case TeamMember::Run: { if (!m_isWild) break; Player* self = qobject_cast(teamMember->containment()); const int numFlee = self->active().size(); bool canRun = true; foreach (Player* player, m_players) { if (self == player) continue; foreach (TeamMember* active, player->active()) { for (int i = 0; (i < numFlee) && canRun; ++i) { if (!active->species()->fleeChance().poll()) { canRun = false; break; } } } if (!canRun) break; } if (canRun) self->exitArena(); break; } case TeamMember::Skip: case TeamMember::Timeout: case TeamMember::Invalid: break; } checkForLosers(); } void Sigbattle::Arena::setupBattle() { foreach (Player* player, m_players) player->enterArena(this); } void Sigbattle::Arena::distributeWinnings() { foreach (Player* player, m_players) { if (!m_spoils.contains(player)) continue; Spoil spoil = m_spoils[player]; const int net = spoil.first - spoil.second; if (net < 0) player->takeMoney(-net); else if (0 < net) player->giveMoney(net); } } void Sigbattle::Arena::checkForLosers() { foreach (Player* player, m_players) { } } Sigbattle::TeamMember* Sigbattle::Arena::findMember(const QUuid& id) { foreach (Player* player, m_players) { TeamMember* member = player->findMember(id); if (member) return member; } return NULL; }