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.