root/traintris/gameboard.py @ 198

Revision 198, 17.7 KB (checked in by andefodahl, 23 months ago)

works now x(

Line 
1from eventmanager import *
2from cell import *
3from constants import *
4from sets import Set
5from comments import *
6
7#---------------------------------------------------------------------------------
8# The overall class that codes for the game model - this includes the grid that
9# contains the terrain and game organisms, as well as codes for the game logic
10# involved in correctly placing them
11class GameBoard:
12
13    #------------------------------------------------------------------
14    def __init__(self, evManager, height, width, screen):
15               
16        self.numbers = gameNumbers().numbers
17        self.comments = Comments().comments
18        self.STATE_PREPARING = 0
19        self.STATE_RUNNING = 1
20        self.STATE_PAUSED = 2 
21
22        self.evManager = evManager
23        self.evManager.RegisterListener(self)
24   
25        self.state = self.STATE_PREPARING
26       
27        self.height = height
28        self.width = width
29
30        self.grid = []
31        self.output = []
32
33        self.web = FoodWeb()
34        self.foodweb = self.web.foodweb
35       
36        self.selectSpecies = ""
37        self.selectType = ""
38        self.foodType = []
39        self.selectRange = 0
40        self.foodneeded = 0 
41
42        self.row = 0
43        self.col = 0
44
45        self.screen = screen
46        self.font = pygame.font.SysFont(None, 35)
47
48
49        self.tutorial = True
50
51        self.day = 1
52
53    #------------------------------------------------------------------ 
54    # Method that initializes the game upon startup - randomly generates
55    # a map of different terrain types
56    def start(self, height, width):
57        for row in range(height):
58            self.grid.append([])
59            self.output.append([])
60            for column in range(width):
61                cells = Cell()
62                if cells.terrainType() == 2:
63                    ev = ChangeTileEvent(19-column, 19-row, 2)
64                    self.evManager.Post(ev)
65                if cells.terrainType() == 3:
66                    ev = ChangeTileEvent(19-column, 19-row, 1)
67                    self.evManager.Post(ev)   
68                self.grid[row].append(cells)
69        self.state = self.STATE_RUNNING
70        species = "Tree" # maybe change this to a null species?
71        ev = CharacterSelectRequest(species, 0)
72        self.evManager.Post(ev)
73        ev = GameStartedEvent(self)
74        self.evManager.Post(ev)
75
76    #------------------------------------------------------------------
77    def getRows(self):
78        return self.width
79
80    #------------------------------------------------------------------
81    def getCols(self):
82        return self.height
83
84    #------------------------------------------------------------------
85    # This method is called when the type of organism being placed changes
86    # and is responsible for chanigng all relavant data memembers such that
87    # the correct organism is placed in a suitable manner       
88    def determineType(self, organism):
89        index = self.web.lookup(organism)
90        foodsources = len(self.foodweb[index]) - 1
91        self.foodType = []
92        for i in range(foodsources):
93            self.foodType.append(self.foodweb[index][i+1])
94        self.selectRange = self.foodweb[index][0][2]
95        self.foodneeded = self.foodweb[index][0][1]
96
97    #------------------------------------------------------------------
98    # addOrganism is responsible for placing an organism in the appropriate
99    # place when user input calls for it - calls helper functions found
100    # below in order to use the game logic to determine if the action is
101    # viable
102    def addOrganism(self, row, column):
103   
104        if row < self.numbers["size1"] or row > self.numbers["size2"] - 1 \
105        or column < self.numbers["size1"] or column > self.numbers["size2"] - 1:
106            ev = Message("You cannot place organisms here", 
107                         "You clicked outside the gameboard", 
108                         "Click inside the gameboard to place animals!",
109                         False, False)
110            self.evManager.Post(ev)
111            pygame.display.update()
112            return 0
113   
114        #if you are trying to remove elements, use appropriate helper function
115        if self.selectSpecies == "remove":
116            if self.removeOrganism(row, column):
117                return 2
118
119        #Use unique logic if trying to place a human
120        if self.selectSpecies == "Human":
121            viable = self.viableHumanAdd(row, column)
122       
123        #Determine if the given placement is a viable placement according to the game logic
124        else:
125            viable = self.viableAdd(row, column)
126
127        #Normal placement, no other variables
128        if viable == 2:
129            self.grid[row][column].addOrganism(self.selectSpecies,
130                                               self.selectType,
131                                               self.selectRange, self.food)
132            return 1
133
134        #Placing a plant on good soil - increase the amount of food given
135        elif viable == 3:
136            self.grid[row][column].addOrganism(self.selectSpecies,
137                                               self.selectType,
138                                               self.selectRange, self.food +1)
139            return 1
140
141        #Winning condition - you placed a human
142        elif viable == 4:
143            self.grid[row][column].addOrganism(self.selectSpecies,
144                                               self.selectType,
145                                               self.selectRange, self.food +1)
146
147            self.evManager.Post(GameOver())
148                               
149            return 1
150
151        #Incorrect placement - nothing happens
152        else:
153            return 0
154     
155
156    #-------------------------------------------------------------------
157    #Function that checks to see whether you can delete the organism found
158    #in the given cell, and does so if possible
159    def removeOrganism(self, row, column):
160        if not self.grid[row][column].isFull(): 
161            return 1
162        else:
163            if self.stealFood(row, column):
164                self.grid[row][column].clearCell()
165                return 1
166           
167    #-------------------------------------------------------------------
168    # helper function for viable add that checks to determine if there are
169    # any elements of the game state that would preclude the placement of
170    # an organism at the particular spot - food levels, terrain is already
171    # occupied, unsuitable terrain, etc.
172    def viableAdd(self, row, column):
173   
174        if row < self.numbers["size1"] or row > self.numbers["size2"] -1 \
175        or column < self.numbers["size1"] or column > self.numbers["size2"] - 1:
176            ev = Message(self.comments["message11"], 
177                         self.comments["message12"], 
178                         self.comments["message13"],
179                         False, False)
180            self.evManager.Post(ev)
181            pygame.display.update()
182            return 1
183   
184   
185        if self.grid[row][column].isFull():
186            ev = Message(self.comments["message21"],
187                         self.comments["message22"],
188                         self.comments["message23"],
189                         False, False)
190            self.evManager.Post(ev)
191            pygame.display.update()
192            return 1
193
194        terrain = self.grid[row][column].terrainType()
195        ##print "Terrain type: " + str(terrain)
196
197        #Unusable Terrain
198        if terrain == 3:
199            ev = Message(self.comments["message31"],
200                         self.comments["message32"],
201                         self.comments["message33"],
202                         False, False)
203            self.evManager.Post(ev)
204            pygame.display.update()
205            return 1
206
207        #Plant Game Logic
208        if self.selectRange == 1:
209            ##print "Sunlight: " + str(self.day)
210            if self.day >= self.numbers["season1"] and self.day < self.numbers["season2"] + 1:
211                if self.foodType[0] == "Light":
212                    ev = Message(self.comments["message41"],
213                                 self.comments["message42"],
214                                 self.comments["message43"],
215                                 False, False)
216                    self.food = 1
217                    self.evManager.Post(ev)
218                    pygame.display.update() 
219                    if  terrain == 1:
220                        return 2
221                    elif terrain == 2:
222                        return 3
223                else:
224                    ev = Message(self.comments["message51"],
225                                 self.comments["message52"],
226                                 self.comments["message53"],
227                                 False, False)
228                    self.evManager.Post(ev)
229                    pygame.display.update()
230                    return 1
231
232            elif self.day >= self.numbers["season2"] + 1 and self.day < self.numbers["season3"]:
233                if self.foodType[0] == "Winter":
234                    ev = Message(self.comments["message61"],
235                                 self.comments["message62"],
236                                 self.comments["message63"],
237                                 False, False)
238                    self.food = 1
239                    self.evManager.Post(ev)
240                    pygame.display.update()
241                    if  terrain == 1:
242                        return 2
243                    elif terrain == 2:
244                        return 3
245                else:
246                    ev = Message(self.comments["message71"],
247                                 self.comments["message72"],
248                                 self.comments["message73"],
249                                 False, False)
250                    self.evManager.Post(ev)
251                    pygame.display.update()
252                    return 1
253               
254        foodsources = self.checkRange(row, column)
255
256        # Detects if you have not selected an organism yet
257        if not hasattr(self, 'food'):
258            ev = Message(self.comments["message81"], 
259                         self.comments["message82"],
260                         self.comments["message83"],
261                         False, False)
262            self.evManager.Post(ev)
263            pygame.display.update()
264            return 1
265
266        # normal game logic
267        if foodsources >= self.foodneeded:
268            self.grid[row][column].foodsources = foodsources
269            self.grid[row][column].foodquota = self.foodneeded
270            self.grid[row][column].foodtype = self.foodType
271            ev = Message(self.comments["message91"] + str(self.selectSpecies) + "!",
272                         self.comments["message92"],
273                         self.comments["message93"],
274                         False, False)
275            self.evManager.Post(ev)
276            return 2
277
278
279        else:
280            ev = Message(self.comments["message01"],
281                         self.comments["message02"],
282                         self.comments["message03"],
283                         False, False)
284            self.evManager.Post(ev)
285            pygame.display.update()
286            return 1
287
288#--------------------------------------------------------
289# Human Logic and helper functions
290    def viableHumanAdd(self, row, column):
291        foodDict = {}
292        foodDict = self.checkHumanRange(row, column, foodDict)
293        humanDiet = {"Snake": 1, "Fox": 1, "Falcon": 1, "Lion": 1, "Tiger" : 1, "Bear" : 1, "Lynx" : 1, "Wolf" : 1, "Snake" : 1}
294        if self.compareDiet(humanDiet, foodDict):
295            return 4
296        else:
297            return 0
298   
299    def compareDiet(self, humanDiet, foodDict):
300        ##print humanDiet.keys()
301        ##print foodDict.keys()
302        for i in humanDiet.keys():
303            if i not in foodDict.keys():
304                return False
305        return True
306
307           
308    def checkHumanRange(self, row, column, foodDict):
309        for i in range(row - self.selectRange, row+self.selectRange + 1):
310            for j in range(column - self.selectRange, column + self.selectRange +1):
311                if i == row and j == column:
312                    continue
313                elif i >= self.numbers["size1"] and i < self.numbers["size2"] \
314                and j >= self.numbers["size1"] and j < self.numbers["size2"]:
315                    k = self.grid[i][j].cellType()
316                    if k == "empty":
317                        continue
318                    elif k in foodDict.keys():
319                        foodDict[k] = foodDict[k]+1
320                    else:
321                        foodDict[k] = 1
322                       
323        return foodDict
324   
325
326
327
328
329    #--------------------------------------------------------------------
330    # A helper function for vaible add that checks every grid square and
331    # returns the total amount of food that is found in the organisms
332    # vicinity
333    def checkRange( self, row, column):
334        foodsources = 0
335        for i in range(row - self.selectRange, row + self.selectRange + 1):
336            for j in range(column - self.selectRange, column + self.selectRange + 1):
337                if i == row and j == column:
338                    continue
339                elif i >= self.numbers["size1"] and i < self.numbers["size2"] \
340                and j >= self.numbers["size1"] and j < self.numbers["size2"]:
341                    k = self.grid[i][j].cellType()
342                    o = self.grid[i][j].isUsable()
343                    for z in range(len(self.foodType)):
344
345                        if self.foodType[z][0] == k and o:   
346                            self.grid[i][j].changeStatus()
347                            self.grid[i][j].eatenRow = row
348                            self.grid[i][j].eatenCol = column
349                            if self.grid[i][j].organism.range == 1 and \
350                               self.grid[i][j].terrainType() == 2:
351                                self.grid[i][j].organism.food = 2
352                                foodsources += 2
353                                break
354
355                            self.grid[i][j].organism.food = self.foodType[z][1]
356                            foodsources += self.foodType[z][1]
357
358                        elif self.foodType[z][0] == k and self.stealFood( i, j ):
359                            self.grid[i][j].eatenRow = row
360                            self.grid[i][j].eatenCol = column
361                            self.grid[i][j].organism.food = self.foodType[z][1]
362                            foodsources += self.foodType[z][1]
363
364        return foodsources
365
366    #--------------------------------------------------------------------
367    # Helper function that codes for interactions of multiple organisms
368    # in relation to excess food - if one organism has too much food this
369    # method allows a newly placed one to "steal" it from them if needed
370    def stealFood( self, row, column):
371        eaten = self.grid[row][column]
372        i = eaten.eatenRow
373        j = eaten.eatenCol
374        eater = self.grid[i][j]
375        if eater.cellType() == 0 or eater.cellType() == "" or \
376           eater.cellType() == "empty":
377            return True
378        if eater.foodsources > eater.foodquota:
379            self.grid[i][j].foodsources -= eaten.foodAmount()
380            return True
381
382    #--------------------------------------------------------------------
383    # Function that manages the seasons and changes them at the appropriate
384    # times
385    def manageSeasons(self):
386        if self.day < self.numbers["season3"]:
387            if self.day == self.numbers["season2"]:
388                counter = str(self.numbers["season2"] - 1)
389                ev2 = SeasonChangeEvent()
390                self.evManager.Post(ev2)
391           
392            elif self.day < self.numbers["season2"]:
393                counter = str(self.numbers["season2"] - self.day)
394            elif self.day > self.numbers["season2"] - 1 and self.day < self.numbers["season3"] - 1:
395                counter = str(self.numbers["season3"] - self.day)
396            self.day += 1
397           
398        else:
399            counter = str(self.numbers["season2"] - 1)
400            self.day = 1
401            ev2 = SeasonChangeEvent()
402            self.evManager.Post(ev2)
403           
404    #--------------------------------------------------------------------
405    # Helper function that displays the info of a particular cell
406    def displayInfo( self, row, column ):
407        self.grid[row][column].displayInfo()
408           
409    #--------------------------------------------------------------------
410    # Notify method responsible for interacting and recieving input from
411    # the event manager
412    def Notify(self, event):
413       
414        if isinstance(event, TickEvent):
415            if self.state == self.STATE_PREPARING:
416                self.start(20, 20)
417                ev = MapBuiltEvent(self)
418                self.evManager.Post(ev)
419                self.state = self.STATE_RUNNING
420                           
421        if isinstance(event, CharacterPlaceEvent) and (not self.tutorial):
422            if event.permission == 0:
423                if self.addOrganism(event.row, event.column) == 1:
424                    self.manageSeasons()
425                    ev = CharacterPlaceEvent(event.column, event.row, 1)
426                    self.evManager.Post(ev)
427                elif self.addOrganism(event.row, event.column) == 2:
428                    ev = RemoveEvent(event.row, event.column)
429                    self.evManager.Post(ev)
430
431
432        if isinstance(event, CharacterSelectRequest) and (not self.tutorial):
433            self.determineType( event.species)
434            self.selectSpecies= event.species
435               
436        if isinstance(event, ChangeTutorial):
437            self.tutorial = not(self.tutorial)
438            pygame.display.update()
439
440        if isinstance(event, CursorBoxSelectEvent):
441            self.row = event.row
442            self.col = event.col
443           
444        if isinstance(event, RemoveSelect):
445            self.selectSpecies = "remove"
446           
447
Note: See TracBrowser for help on using the browser.