1 ########################################################
2 #Copyright (c) 2006 Russ Adams, Sean Eubanks, Asgard Contributors
3 #This file is part of Asgard.
5 #Asgard is free software; you can redistribute it and/or modify
6 #it under the terms of the GNU General Public License as published by
7 #the Free Software Foundation; either version 2 of the License, or
8 #(at your option) any later version.
10 #Asgard is distributed in the hope that it will be useful,
11 #but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 #GNU General Public License for more details.
15 #You should have received a copy of the GNU General Public License
16 #along with Asgard; if not, write to the Free Software
17 #Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 ########################################################
19 from statistic
import *
20 from os
import listdir
22 from equiption
import *
24 from eventtype
import *
30 class ConsoleController
:
31 """ Model: ConsoleController Class """
34 """ A link to the Battle. Set by constructor. """
37 """ A link to ConsoleView. Set by constructor. """
40 """ Are we in debug mode? This prints out extra information during program execution. """
42 def __init__(self
,debug
,battle
,view
):
43 """ Sets the links for Battle and ConsoleView so that each of them can access ConsoleController and themselves. It sets the mode of gameplay, normal or debug. Afterwards, the game loop starts. This function does not automatically load nor save binary data! Additionally, it uses self.loadStaticData() to load EventTypes and non-playable Fighters. """
46 self
.__battle
= battle
49 battle
.setController(self
)
51 view
.setController(self
)
52 view
.setBattle(battle
)
56 def getBattleCommand(self
,vp
,hp
,f
):
57 """ Prints out an event selection menu and collects a choice from the user. It returns the enemy selected for attack and the type of attack. Should use pygame's event driven input functionallity. """
61 print "\033[1;34m[SELCT]\033[1;0m Turn:" + f
.getName() + "; HP:" + str(f
.getStat("hp").getCurrent()) + "/" + str(f
.getStat("hp").getMax()) + " - MP:"+str(f
.getStat("mp").getCurrent())+"/"+str(f
.getStat("mp").getMax())
63 self
.__view
.printEventTypeMenu(f
,self
.__battle
.getEventTypeList())
65 t
= self
.__battle
.getEventType(f
.getEventTypes(self
.__battle
.getEventTypeList())[int(n
)-1])
67 if t
.getName() == "quit":
70 self
.__view
.printTargetSelectMenu(vp
,hp
)
73 if vp
.sizeOfParty() - int(n
) >= 0:
74 d
= vp
.getFighter(int(n
)-1)
77 d
= hp
.getFighter(int(n
)-vp
.sizeOfParty()-1)
80 def getMenuCommand(self
):
81 """ Prints out the startup menu, via ConsoleController.printStartupMenu() then obtains user input. Returns result. """
83 self
.__view
.printStartupMenu()
96 """ Show dummy menu. Get user choices. If New Game selected, call self.createNewSave(..). If Load Game selected, call self.load(..). If Save Game selected, call self.save(..) (show only if game loaded), show menu again. If Random Battle selected: (1)Create a random battle. (self.createRandomBattle(..)). (2)Print out the state of affairs before the battle begins. Executes Battle.nextTurn() once. The experience passed to giveExp should be the sum of the defeated party's experience. (3)After battle, show dummy menu again. If Quit selected, end program. """
98 print "Asgard Free Software RPG - Testing Module"
100 self
.loadStaticData(False)
105 choice
= self
.getMenuCommand()
108 self
.unloadStaticData()
109 self
.loadStaticData(True)
113 print "Path to Save File: ",
114 path
= sys
.stdin
.readline()
115 self
.load("" + path
.strip() + "")
119 print "Path to Save File: ",
120 path
= sys
.stdin
.readline()
121 self
.save("" + path
.strip() + "")
126 if self
.__battle
.getParty1() == None:
127 print "No game loaded."
130 self
.createRandomBattle()
131 print "============================================================="
135 print "Battle Starts."
136 self
.__view
.printState()
138 # initialize the event checker boolean
141 while not self
.__battle
.isOver():
143 wereEvents
= self
.__battle
.nextTurn()
145 # only print out state if something actually happened
147 self
.__view
.printState()
149 if self
.__battle
.getParty1().isAlive():
152 # sum exp from enemy party
154 for f
in self
.__battle
.getParty2().getFighters():
155 exp
+= f
.getStat("exp").getMax()
157 # hero party gets exp
158 self
.__battle
.getParty1().giveExp(exp
)
161 print "Final Results"
162 print "============================================================="
163 self
.__view
.printParty(self
.__battle
.getParty1())
164 print "============================================================="
165 print "Victory Fanfare. Hand's party wins "+str(exp
)+" exp!"
167 for f
in self
.__battle
.getParty1().getFighters():
168 # remove all statuses
169 for s
in f
.getStatus():
171 f
.getStat("mp").setCurrent(f
.getStat("mp").getMax())
174 print "Game Over. Asgard mourns."
176 # clear out the hero party - they're dead!
177 self
.__battle
.setParty1(None)
180 def load(self
,savefile
):
181 """ Destroy hero Party and playable Fighters. Construct new hero Party and playable Fighters. """
183 #clear party1 and it's fighters
184 self
.__battle
.setParty1(Party("Heroes"))
187 fptr
= open(savefile
,"rb")
194 # number of bytes read in so far
197 while readin
!= size
:
198 #read in struct descriptor
200 tstring
= fptr
.read(struct
.calcsize("!B"))
201 [type] = struct
.unpack("!B",tstring
)
202 readin
+= struct
.calcsize("!B")
206 fstring
= fptr
.read(struct
.calcsize("!20s20s20s20s20s20sB7I6B"))
207 readin
+= struct
.calcsize("!20s20s20s20s20s20sB7I6B")
212 fighter
= Fighter(binary
=fstring
)
213 self
.__battle
.getParty1().addFighter(fighter
)
218 def save(self
,savefile
):
219 """ Calls Party.getBinaryString() for hero Party. Calls Fighter.getBinaryString() for all playable Fighters. Concatenates binary string and writes to save file. """
221 # Retrieving playable fighters
222 fighters
= self
.__battle
.getParty1().getFighters()
224 # Writing each fighter to savefile
225 fptr
= open(savefile
,"wb")
228 # Convert fighter f to binary string
229 binStr
= f
.toBinaryString()
231 # Write binary string to savefile
232 fptr
.write(binStr
.strip())
236 def createRandomBattle(self
):
237 """ Randomly selects some number (1 to 6) of monsters, and randomly determines which monsters they are. Copies each monster to populate an enemy party. """
239 self
.__battle
.setParty2(Party("Villains"))
241 partySize
+= random
.randint(-1,2)
242 for x
in range(0, partySize
):
243 monstI
= random
.randint(0,len(self
.__battle
.getMonsters())-1)
245 monster
= copy
.deepcopy(self
.__battle
.getMonsters()[monstI
])
246 self
.__battle
.getParty2().addFighter(monster
)
248 for f
in self
.__battle
.getParty1().getFighters():
249 spd
= f
.getStat("spd").getCurrent()
250 tom
= round((1/float(spd
)*100))
251 f
.getStat("tom").setCurrent(tom
)
252 f
.getStat("tom").setMax(tom
)
253 f
.getStat("canMove").setCurrent(1)
254 f
.getStat("ai").setCurrent(0)
256 self
.__battle
.setCurrentTime(0)
258 def loadStaticData(self
,newGame
):
259 """ Loads EventTypes and non-playable/initial playable Fighters. (at some point, other things too). Utilizes the Fighter xml constructor. By default it loads fighter objects that are non-playable into Battle.monsters, but when newGame is True, it also creates the hero party from the files in ./data/fighter/playable. It does not load playable fighters into Battle.monsters. """
261 dir = listdir('./data/eventtypes/')
263 self
.__battle
.setEventTypeList([])
270 etTree
= libxml2
.parseFile('./data/eventtypes/'+et
)
273 eventType
= EventType(etTree
)
274 self
.__battle
.getEventTypeList().append(eventType
)
277 self
.__battle
.setParty1(Party("Heroes"))
279 ### Loading fighters ###
280 dir = listdir('./data/fighter/')
283 # f cannot be a "." file
287 # Create Fighter XML Tree
288 fTree
= libxml2
.parseFile('./data/fighter/'+f
)
290 # Create Fighter Object
291 fighter
= Fighter(fTree
=fTree
)
293 # Add fighter to respective party (1 or 2)
294 if fighter
.getPlayable() and newGame
:
295 self
.__battle
.getParty1().addFighter(fighter
)
296 elif not fighter
.getPlayable():
297 self
.__battle
.getMonsters().append(fighter
)
299 def unloadStaticData(self
):
300 """ Clears out all monsters and EventTypes. """
302 # Clearing out monsters
303 self
.__battle
.setMonsters([])
305 # Clearing out EventTypes
306 self
.__battle
.setEventTypeList([])