ActionQueue.cpp

Go to the documentation of this file.
00001 /*
00002 SagaEngine library
00003 Copyright (c) 2002-2006 Skalden Studio AS
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to distribute the library under the terms of the 
00010 Q Public License version 1.0. Be sure to read and understand the license
00011 before using the library. It should be included here, or you may read it
00012 at http://www.trolltech.com/products/qt/licenses/licensing/qpl
00013 
00014 The original version of this library can be located at:
00015 http://www.sagaengine.com/
00016 
00017 Rune Myrland
00018 rune@skalden.com
00019 */
00020 
00021 
00022 #include "ActionQueue.hpp"
00023 #include "../schema/SimSchema.hpp"
00024 #include "ActionComponent.hpp"
00025 
00026 
00027 namespace se_core {
00028 
00029     unsigned short ActionQueue
00030     ::createActionChannelId() {
00031         static unsigned short idPool = 0;
00032         return idPool++;
00033     }
00034 
00035 
00036     ActionQueue
00037     ::ActionQueue() :
00038         currentTurn_(0), currentInitiative_(0), isPerforming_(false)
00039         , scheduleCurrentTurn_(new ActorList::iterator_type[INITIATIVES_PER_TURN])
00040         , scheduleFutureTurns_(new ActorList::iterator_type[MAX_TURNS]) {
00041         channel_ = createActionChannelId();
00042         for(unsigned short i = 0; i < INITIATIVES_PER_TURN; ++i) {
00043             scheduleCurrentTurn_[ i ] = ActorList::end();
00044         }
00045         for(unsigned short i = 0; i < MAX_TURNS; ++i) {
00046             scheduleFutureTurns_[ i ] = ActorList::end();
00047         }
00048     }
00049 
00050     ActionQueue
00051     ::~ActionQueue() {
00052         delete[] scheduleCurrentTurn_;
00053         delete[] scheduleFutureTurns_;
00054     }
00055 
00056 
00057     void ActionQueue
00058     ::performScheduledActions(long when) {
00059         isPerforming_ = true;
00060         ActorList::iterator_type it = scheduleCurrentTurn_[ currentInitiative_ ];
00061         while(it != ActorList::end()) {
00062             ActionComponent* a = actorList_.next(it);
00063             a->perform(when, channel_);
00064         }
00065         isPerforming_ = false;
00066     }
00067 
00068 
00069     void ActionQueue
00070     ::scheduleNextActions(long when) {
00071         ActorList::iterator_type it = scheduleCurrentTurn_[ currentInitiative_ ];
00072         while(it != ActorList::end()) {
00073             ActionComponent* a = actorList_.next(it);
00074             a->scheduleNextAction(when, channel_);
00075         }
00076     }
00077 
00078 
00079     unsigned short ActionQueue
00080     ::add(ActionComponent &actor, short duration) {
00081         unsigned short turn = futureTurn(duration);
00082 
00083         if(turn == currentTurn_) {
00084             unsigned short initiative = futureInitiative(duration);
00085             actorList_.add(&actor, scheduleCurrentTurn_[ initiative ]);
00086         }
00087         else {
00088             actorList_.add(&actor, scheduleFutureTurns_[ turn ]);
00089         }
00090 
00091         return futureSchedule(duration);
00092     }
00093 
00094 
00095     bool ActionQueue
00096     ::disrupt(ActionComponent &actor) {
00097         bool didDisrupt = false;
00098         unsigned short schedule = actor.actionSchedule(channel_);
00099         unsigned short turn = turnFromSchedule(schedule);
00100         if(turn == currentTurn_) {
00101             unsigned short initiative = initiativeFromSchedule(schedule);
00102             // Actions that are finished this initiative should be completed.
00103             // Makes most sense that an action should not be able to disrupt an
00104             // action in the same initiative, and also solves some hard
00105             // concurrency problems...
00106             if(!isPerforming_ || initiative != currentInitiative_) {
00107                 actorList_.remove(&actor, scheduleCurrentTurn_[ initiative ]);
00108                 didDisrupt = true;
00109             }
00110         }
00111         else {
00112             actorList_.remove(&actor, scheduleFutureTurns_[ turn ] );
00113             didDisrupt = true;
00114         }
00115 
00116         return didDisrupt;
00117     }
00118 
00119 
00120     void ActionQueue
00121     ::beginNextInitiative() {
00122         actorList_.removeChain(scheduleCurrentTurn_[ currentInitiative_  ]);
00123 
00124         currentInitiative_ = futureInitiative(1);
00125         if(currentInitiative_ == 0) {
00126             beginNextTurn();
00127         }
00128     }
00129 
00130 
00131     void ActionQueue
00132     ::beginNextTurn() {
00133         currentTurn_ = futureTurn(INITIATIVES_PER_TURN);
00134 
00135         ActorList::iterator_type it = scheduleFutureTurns_[ currentTurn_ ];
00136         while(it != ActorList::end()) {
00137             ActionComponent* a = actorList_.next(it);
00138             unsigned short initiative = initiativeFromSchedule(a->actionSchedule(channel_));
00139             actorList_.add(a, scheduleCurrentTurn_[ initiative ]);
00140         }
00141         actorList_.removeChain(scheduleFutureTurns_[ currentTurn_ ]);
00142     }
00143 
00144 
00145     void ActionQueue
00146     ::reset() {
00147         actorList_.clear();
00148         currentTurn_ = 0;
00149         currentInitiative_ = 0;
00150         for(unsigned short i = 0; i < INITIATIVES_PER_TURN; ++i) {
00151             scheduleCurrentTurn_[ i ] = ActorList::end();
00152         }
00153         for(unsigned short i = 0; i < MAX_TURNS; ++i) {
00154             scheduleFutureTurns_[ i ] = ActorList::end();
00155         }
00156     }
00157 
00158 }

Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:11 2007 by Doxygen version 1.3.9.1.

SourceForge.net Logo