def Summary(g): lev = dict() lev[MENU_TUTORIAL] = "a Tutorial" lev[MENU_BEGINNER] = "a Beginner" lev[MENU_INTERMEDIATE] = "an Intermediate" lev[MENU_EXPERT] = "an Expert" lev[MENU_PEACEFUL] = "a Peaceful" assert g.challenge != None assert g.challenge in lev New_Mail("You are playing " + lev[g.challenge] + " game.") New_Mail("Win the game by upgrading your city to tech level %u." % DIFFICULTY.CITY_MAX_TECH_LEVEL)
def Restore(cmd): global game (g2, result) = save_game.Load(game, cmd) if (result == None): game = g2 ui.net = game.net mail.Initialise() assert game.challenge != None DIFFICULTY.Set(game.challenge) New_Mail("Game restored. It is the " + game.season_fx.name + " season.") else: New_Mail(result)
def Restore(g, cmd): (g2, result) = save_game.Load(g, cmd) if (result == None): g = g2 ui.net = g.net mail.Initialise() mail.Set_Day(g.game_time.Get_Day()) assert g.challenge != None DIFFICULTY.Set(g.challenge) New_Mail( f"Game restored. It is currently {g.season_fx.name} season.") else: New_Mail(result) return g
def Begin_Upgrade(self): if ( self.tech_level >= PIPE_MAX_TECH_LEVEL ): New_Mail("Pipe cannot be upgraded further.") sound.FX("error") elif ( self.Needs_Work() ): New_Mail("Pipe must be operational before an upgrade can begin.") sound.FX("error") else: sound.FX("crisp") # Upgrade a pipe for lower resistance and more health. self.tech_level += 1 self.max_health += int( PIPE_UPGRADE_WORK_FACTOR * self.length * HEALTH_UNIT ) self.complete = False self.resistance *= PIPE_UPGRADE_RESISTANCE_FACTOR
def Destroy(self, node, by=None): if (isinstance(node, Pipe)): self.__Destroy_Pipe(node) return if ((node == self.hub) or (not isinstance(node, Building))): return # indestructible sound.FX("destroy") if (isinstance(node, Node)): # work on a copy, as __Destroy_Pipe will change the list. pipe_list = [pipe for pipe in node.pipes] for pipe in pipe_list: self.__Destroy_Pipe(pipe) gpos = node.pos if (gpos not in self.ground_grid): return # not on map if (self.ground_grid[gpos] != node): return # not on map (something else is there) self.dirty = True if (by != None): New_Mail(node.name_type + " destroyed by " + by + ".") node.Prepare_To_Die() self.__List_Destroy(self.node_list, node) rnode = node.Restore() if (rnode == None): del self.ground_grid[gpos] else: self.ground_grid[gpos] = rnode
def Do_Upgrade(self): if ( self.tech_level >= NODE_MAX_TECH_LEVEL ): New_Mail("Node cannot be upgraded further.") sound.FX("error") elif ( self.Needs_Work() ): New_Mail("Node must be operational before an upgrade can begin.") sound.FX("error") else: sound.FX("crisp") # Upgrade a node to get a higher capacity and more health. # More health means harder to destroy. # More capacity means your network is more resilient. self.tech_level += 1 self.max_health += NODE_UPGRADE_WORK * HEALTH_UNIT self.complete = False
def Add_Pipe(self, n1, n2): if ( n1.Is_Destroyed() or n2.Is_Destroyed() ): sound.FX("error") New_Mail("Nodes are destroyed.") return False # What's in the pipe's path? path = extra.More_Accurate_Line(n1.pos, n2.pos) other_pipes = set([]) other_items = set([]) for gpos in path: if ( self.pipe_grid.has_key(gpos) ): other_pipes |= set(self.pipe_grid[ gpos ]) elif ( self.ground_grid.has_key(gpos) ): other_items |= set([self.ground_grid[ gpos ]]) other_items -= set([n1,n2]) if ( len(other_items) != 0 ): sound.FX("error") New_Mail("Pipe collides with other items.") print repr(other_items) return False for p in other_pipes: if ( not p.Is_Destroyed () ): if ((( p.n1 == n1 ) and ( p.n2 == n2 )) or (( p.n1 == n2 ) and ( p.n2 == n1 ))): sound.FX("error") New_Mail("There is already a pipe there.") return False if ( intersect.Intersect((p.n1.pos,p.n2.pos), (n1.pos,n2.pos)) != None ): sound.FX("error") New_Mail("That crosses an existing pipe.") return False sound.FX("bamboo1") pipe = Pipe(n1, n2) self.pipe_list.append(pipe) for gpos in path: if ( not self.pipe_grid.has_key(gpos) ): self.pipe_grid[ gpos ] = [pipe] else: self.pipe_grid[ gpos ].append(pipe) return True
def Summary(): lev = dict() lev[MENU_TUTORIAL] = "a Tutorial" lev[MENU_BEGINNER] = "a Beginner" lev[MENU_INTERMEDIATE] = "an Intermediate" lev[MENU_EXPERT] = "an Expert" assert game.challenge != None assert lev.has_key(game.challenge) New_Mail("You are playing " + lev[game.challenge] + " game.")
def Do_Work(self): if ( self.city_upgrade > 0 ): self.city_upgrade -= 1 if ( self.city_upgrade == 0 ): self.tech_level += 1 self.steam.Capacity_Upgrade() sound.FX("cityups") New_Mail("City upgraded to level %d of %d!" % ( self.tech_level, DIFFICULTY.CITY_MAX_TECH_LEVEL ) )
def Add_Grid_Item(self, item, inhibit_effects=False): gpos = item.pos if ( item.Is_Destroyed() ): if ( not inhibit_effects ): New_Mail("Item is destroyed.") return False if ( self.pipe_grid.has_key(gpos) ): # There might be a pipe in the way. Then again, # it may have been destroyed already. for pipe in self.pipe_grid[ gpos ]: if ( pipe.Is_Destroyed() ): continue if ( extra.Intersect_Grid_Square(gpos, (pipe.n1.pos, pipe.n2.pos)) ): if ( not inhibit_effects ): New_Mail("Can't build there - pipe in the way!") sound.FX("error") return False if (( self.ground_grid.has_key(gpos) ) and ( isinstance(self.ground_grid[ gpos ], Building) )): if ( not inhibit_effects ): New_Mail("Can't build there - building in the way!") sound.FX("error") return False if ( isinstance(item, Node) ): self.node_list.append(item) if ( self.ground_grid.has_key( gpos )): item.Save(self.ground_grid[ gpos ]) self.ground_grid[ gpos ] = item elif ( isinstance(item, Well) ): self.well_list.append(item) self.ground_grid[ gpos ] = item else: assert False # unknown type! return True
def Begin_Upgrade(self): # Upgrade a city for higher capacity # and more work units. Warning: upgraded city # will require more steam! # # Most upgrades use the health system as this # puts the unit out of action during the upgrade. # This isn't suitable for cities: you lose if your # city is out of action. We use a special system. if ( self.city_upgrade == 0 ): if ( self.tech_level < DIFFICULTY.CITY_MAX_TECH_LEVEL ): sound.FX("mechanical_1") self.city_upgrade = self.city_upgrade_start = ( ( CITY_UPGRADE_WORK + ( self.tech_level * DIFFICULTY.CITY_UPGRADE_WORK_PER_LEVEL )) * HEALTH_UNIT ) self.avail_work_units += 1 # Extra steam demand else: New_Mail("City is fully upgraded.") sound.FX("error") else: New_Mail("City is already being upgraded.") sound.FX("error")
def Load_Image(name): global __img_cache key = name if ( __img_cache.has_key(key) ): return __img_cache[ key ] fname = Path(name) try: img = pygame.image.load(fname) except Exception, r: s = "WARNING: Unable to load image '" + fname + "': " + str(r) print "" print s print "" New_Mail(s) img = pygame.Surface((10,10)) img.fill((255,0,0))
def Load_Image(name): global __img_cache key = name if ( key in __img_cache ): return __img_cache[ key ] fname = Path(name) try: img = pygame.image.load(fname) except Exception as r: s = "WARNING: Unable to load image '" + fname + "': " + str(r) print("") print(s) print("") New_Mail(s) img = pygame.Surface((10,10)) img.fill((255,0,0)) i = __img_cache[ key ] = img.convert_alpha() return i
def Main_Loop(screen, clock, xxx_todo_changeme, restore_pos, challenge): # Initialisation of screen things. (width, height) = xxx_todo_changeme menu_margin = height screen.fill((0, 0, 0)) # screen is black during init pygame.display.flip() tutor.Off() draw_obj.Flush_Draw_Obj_Cache() # in case of resize # Grid setup (w, h) = GRID_SIZE assert w == h Set_Grid_Size(height / h) # Windows.. game_screen_rect = Rect(0, 0, menu_margin, height) game_screen_surf = screen.subsurface(game_screen_rect) menu_area = screen.subsurface( Rect(menu_margin, 0, width - menu_margin, height)) menu_width = width - menu_margin # Constraint on resolution applied here: assert menu_width >= 100 def Sc(v): # Original values were for 800x600 - scale that # for whatever the user's screen res happens to be. return (v * height) / 600 margin = Sc(10) x1 = menu_margin + margin menu_width1 = menu_width - (margin * 2) picture = resource.Load_Image("headersm.jpg") picture_rect = picture.get_rect().inflate(10, 10) picture_rect.center = (x1 + (menu_width1 / 2), 0) picture_rect.top = margin picture_surf = screen.subsurface(picture_rect) stats_rect = Rect(x1, picture_rect.bottom + margin, menu_width1, Sc(120)) stats_surf = screen.subsurface(stats_rect) global_stats_rect = Rect(x1, stats_rect.bottom + margin, menu_width1, Sc(110)) global_stats_surf = screen.subsurface(global_stats_rect) controls_rect = Rect(x1, global_stats_rect.bottom + margin, menu_width1, height - (margin + global_stats_rect.bottom + margin)) controls_surf = screen.subsurface(controls_rect) def Special_Refresh(): extra.Tile_Texture( screen, "rivets.jpg", Rect(menu_margin, 0, menu_width, screen.get_rect().height)) edge = Rect(menu_margin, -10, menu_width + 10, screen.get_rect().height + 10) for r in [stats_rect, global_stats_rect, edge]: extra.Line_Edging(screen, r, False) r = picture.get_rect() r.center = picture_surf.get_rect().center extra.Line_Edging(picture_surf, r, False) picture_surf.blit(picture, r.topleft) Special_Refresh() stats_surf.fill((0, 0, 0)) FRAME_RATE = 35 alarm_sound = sound.Persisting_Sound("emergency") teaching = (challenge == MENU_TUTORIAL) # Game data holder g = Game_Data() g.version = startup.Get_Game_Version() g.sysinfo = extra.Get_System_Info() # Steam network initialisation g.net = Network(teaching) DIFFICULTY.Set(MENU_INTERMEDIATE) # Establish equilibrium with initial network. for i in range(300): g.net.Steam_Think() if (g.net.hub.Get_Pressure() >= PRESSURE_GOOD): if (DEBUG): print(i, 'steps required for equilibrium') break assert g.net.hub.Get_Pressure() >= PRESSURE_GOOD # UI setup ui = User_Interface(g.net, (width, height)) inputs = [(controls_rect, ui.Control_Mouse_Down, ui.Control_Mouse_Move), (game_screen_rect, ui.Game_Mouse_Down, ui.Game_Mouse_Move)] exit_options = [(MENU_MENU, "Exit to Main Menu", []), (MENU_QUIT, "Exit to " + extra.Get_OS(), [K_F10])] save_available = [(MENU_SAVE, "Save Game", []), (MENU_LOAD, "Restore Game", []), (None, None, [])] if (challenge == MENU_TUTORIAL): save_available = [] in_game_menu = menu.Menu([(None, None, []), (MENU_MUTE, "Toggle Sound", []), (None, None, [])] + save_available + [(MENU_HIDE, "Return to Game", [K_ESCAPE])] + exit_options) current_menu = in_game_menu flash = True loop_running = True quit = False stats_review = False in_game_menu.Select(None) mail.Initialise() rt_then = time.time() fps_count = 0 fps_time = rt_then autosave_timer = 0 if (restore_pos == None): DIFFICULTY.Set(challenge) # Game variables g.season = SEASON_START g.season_ends = 0 g.season_effect = 0 g.season_fx = Quiet_Season(g.net) g.work_units_used = 0 g.challenge = challenge g.difficulty_level = 1.0 g.work_timer = 0.1 g.game_ends_at = None g.game_running = True g.game_time = gametime.Game_Time() g.historian = [] g.historian_time = 0 g.win = False g.warning_given = False g.wu_integral = 0 mail.Set_Day(g.game_time.Get_Day()) def Summary(g): lev = dict() lev[MENU_TUTORIAL] = "a Tutorial" lev[MENU_BEGINNER] = "a Beginner" lev[MENU_INTERMEDIATE] = "an Intermediate" lev[MENU_EXPERT] = "an Expert" lev[MENU_PEACEFUL] = "a Peaceful" assert g.challenge != None assert g.challenge in lev New_Mail("You are playing " + lev[g.challenge] + " game.") New_Mail("Win the game by upgrading your city to tech level %u." % DIFFICULTY.CITY_MAX_TECH_LEVEL) # Almost ready to start... but are we starting # from a savegame? def Restore(g, cmd): (g2, result) = save_game.Load(g, cmd) if (result == None): g = g2 ui.net = g.net mail.Initialise() mail.Set_Day(g.game_time.Get_Day()) assert g.challenge != None DIFFICULTY.Set(g.challenge) New_Mail( f"Game restored. It is currently {g.season_fx.name} season.") else: New_Mail(result) return g if (restore_pos != None): g.challenge = MENU_INTERMEDIATE g = Restore(g, restore_pos) assert g.challenge != None Summary(g) if (g.challenge == MENU_TUTORIAL): tutor.On((menu_margin * 40) / 100) cur_time = g.game_time.time() # Main loop while (loop_running): if (g.game_running): flash = not flash menu_inhibit = ui.Is_Menu_Open() or not g.game_running # Insert delay... # Hmm, I'm not sure if I know what this does. clock.tick(FRAME_RATE) rt_now = time.time() rt_frame_length = rt_now - rt_then rt_then = rt_now fps_count += 1 if (fps_count > 100): if (DEBUG): print( f"{math.floor(float(fps_count) / (rt_now - fps_time))} fps" ) fps_time = rt_now fps_count = 0 if (not menu_inhibit): if (not tutor.Frozen()): g.game_time.Advance(rt_frame_length) draw_obj.Next_Frame() # Flashing lights on the various items cur_time = g.game_time.time() mail.Set_Day(g.game_time.Get_Day()) ui.Draw_Game(game_screen_surf, g.season_fx) # if ( flash ): # ui.Draw_Selection(picture_surf) if (g.challenge == MENU_TUTORIAL): until_next = [] elif (g.challenge == MENU_PEACEFUL): until_next = [((128, 128, 128), 12, "Peaceful mode")] else: until_next = [( (128, 128, 128), 12, f"{math.floor((g.season_ends - cur_time) + 1)} days until next season)" )] ui.Draw_Stats(stats_surf, [((128, 0, 128), 18, f"Day {g.game_time.Get_Day()}"), ((128, 128, 0), 18, g.season_fx.name + " season")] + until_next + g.season_fx.Get_Extra_Info()) ui.Draw_Controls(controls_surf) if (menu_inhibit): current_menu.Draw(screen) alarm_sound.Set(0.0) stats_back = (0, 0, 0) supply = g.net.hub.Get_Steam_Supply() demand = g.net.hub.Get_Steam_Demand() if (g.net.hub.Get_Pressure() < PRESSURE_DANGER): # You'll lose the game if you stay in this zone # for longer than a timeout. Also, an # alarm will sound. if (g.game_ends_at == None): sound.FX("steamcrit") g.warning_given = True New_Mail("Danger! The City needs more steam!", (255, 0, 0)) g.game_ends_at = cur_time + DIFFICULTY.GRACE_TIME New_Mail( f"Game will end on Day {g.game_ends_at} unless supplies are increased.", (255, 0, 0)) if (flash): demand_colour = (255, 0, 0) if (not menu_inhibit): alarm_sound.Set(0.6) else: demand_colour = (128, 0, 0) stats_back = (100, 0, 0) elif (g.net.hub.Get_Pressure() < PRESSURE_WARNING): g.game_ends_at = None if (flash): demand_colour = (255, 100, 0) if (not menu_inhibit): alarm_sound.Set(0.3) else: demand_colour = (128, 50, 0) stats_back = (50, 25, 0) else: if (g.warning_given): sound.FX("steamres") g.warning_given = False if (g.net.hub.Get_Pressure() < PRESSURE_OK): demand_colour = (128, 128, 0) else: demand_colour = (0, 128, 0) g.game_ends_at = None alarm_sound.Set(0.0) avw = g.net.hub.Get_Avail_Work_Units() wu_unused = avw - g.work_units_used if (not menu_inhibit): global_stats_surf.fill(stats_back) stats.Draw_Stats_Window( global_stats_surf, [(CITY_COLOUR, 18, "Steam Pressure"), (CITY_COLOUR, 18, "Supply : Demand"), (demand_colour, 24, f"{round(supply, 1)} : {round(demand, 1)}"), (None, None, g.net.hub.Get_Pressure_Meter()), (CITY_COLOUR, 0, ""), (CITY_COLOUR, 12, f"{wu_unused} of {avw} work units available"), (None, None, (wu_unused, (255, 0, 255), avw, (0, 0, 0)))]) if (g.challenge == MENU_TUTORIAL): tutor.Draw(screen, g) pygame.display.flip() if (not menu_inhibit): g.season_fx.Per_Frame(rt_frame_length) ui.Frame_Advance(rt_frame_length) # Timing effects if (g.work_timer <= cur_time): # Fixed periodic effects g.work_timer = cur_time + 0.1 g.wu_integral += wu_unused g.work_units_used = g.net.Work_Pulse( g.net.hub.Get_Avail_Work_Units()) g.net.Steam_Think() g.net.Expire_Popups() tutor.Examine_Game(g) if (g.season_effect <= cur_time): # Seasonal periodic effects g.season_effect = cur_time + g.season_fx.Get_Period() g.season_fx.Per_Period() if (((not tutor.Permit_Season_Change()) and (g.season == SEASON_QUIET)) or (g.challenge == MENU_PEACEFUL)): g.season_ends = cur_time + 2 if (g.season_ends <= cur_time): # Season change if (g.season == SEASON_START): g.season = SEASON_QUIET g.season_fx = Quiet_Season(g.net) elif ((g.season == SEASON_QUIET) or (g.season == SEASON_STORM)): g.season = SEASON_ALIEN g.season_fx = Alien_Season(g.net, g.difficulty_level) sound.FX("aliensappr") elif (g.season == SEASON_ALIEN): g.season = SEASON_QUAKE g.season_fx = Quake_Season(g.net, g.difficulty_level) if (not tutor.Active()): # hack... sound.FX("quakewarn") elif (g.season == SEASON_QUAKE): g.season = SEASON_STORM g.season_fx = Storm_Season(g.net, g.difficulty_level) g.difficulty_level *= 1.2 # 20% harder.. sound.FX("stormwarn") else: assert False g.season_ends = cur_time + LENGTH_OF_SEASON g.season_effect = cur_time + (g.season_fx.Get_Period() / 2) if (g.challenge != MENU_PEACEFUL): New_Mail(f"The {g.season_fx.name} season has started.", (200, 200, 200)) just_ended = False if ((g.game_ends_at != None) and (g.game_ends_at <= cur_time) and (g.game_running)): # Game over - you lose g.game_running = False New_Mail("The City ran out of steam.", (255, 0, 0)) New_Mail("Game Over!", (255, 255, 0)) sound.FX("krankor") just_ended = True elif ((g.net.hub.tech_level >= DIFFICULTY.CITY_MAX_TECH_LEVEL) and (g.game_running)): # Game over - you win! g.game_running = False g.win = True New_Mail("The City is now fully upgraded!", (255, 255, 255)) New_Mail("You have won the game!", (255, 255, 255)) sound.FX("applause") just_ended = True if (just_ended): current_menu = in_game_menu = menu.Menu( [(None, None, []), (MENU_REVIEW, "Review Statistics", [])] + exit_options) in_game_menu.Select(None) # Events e = pygame.event.poll() while (e.type != NOEVENT): if e.type == QUIT: loop_running = False quit = True elif e.type == MOUSEBUTTONDOWN or e.type == MOUSEMOTION: if e.type == MOUSEBUTTONDOWN and e.button != 1: if not menu_inhibit: ui.Right_Mouse_Down() elif not menu_inhibit: for rect, click, move in inputs: if rect.collidepoint(e.pos): (x, y) = e.pos x -= rect.left y -= rect.top if e.type == MOUSEMOTION: move((x, y)) else: click((x, y)) elif menu_inhibit: if e.type == MOUSEMOTION: current_menu.Mouse_Move(e.pos) else: current_menu.Mouse_Down(e.pos) elif e.type == KEYDOWN: if not menu_inhibit: ui.Key_Press(e.key) elif menu_inhibit: current_menu.Key_Press(e.key) if DEBUG: # Cheats. if e.key == K_F10: New_Mail("Cheat used: Advanced to next season.") g.season_ends = 0 elif e.key == K_F9: New_Mail("Cheat used: Screen filled with white.") screen.fill((255, 255, 255)) elif e.key == K_F8: # Lose the game cheat # Heh, worst cheat ever. New_Mail("Cheat used: Game ended.") g.game_ends_at = cur_time e = pygame.event.poll() # Any commands from the menu? if menu_inhibit: cmd = current_menu.Get_Command() current_menu.Select(None) # consume command if current_menu == in_game_menu: # It's the normal menu. if cmd == MENU_QUIT: loop_running = False quit = True ui.Reset() # makes menu disappear elif cmd == MENU_MENU: loop_running = False ui.Reset() elif cmd == MENU_SAVE: if (g.game_running): # Switch to alternate menu current_menu = save_menu.Save_Menu(True) elif cmd == MENU_LOAD: current_menu = save_menu.Save_Menu(False) elif cmd == MENU_MUTE: config.cfg.mute = not config.cfg.mute ui.Reset() elif cmd == MENU_REVIEW: loop_running = False stats_review = True ui.Reset() elif cmd != None: # Default option - back to game if (not g.game_running): New_Mail("Sorry - the game has finished") ui.Reset() else: # It's another menu! That means it's the save menu. if cmd != None and cmd >= 0: if not current_menu.Is_Saving(): g = Restore(g, cmd) else: label = f"Day {math.floor(g.game_time.Get_Day())} - {g.season_fx.name} season - {time.asctime()}" g.net.Make_Ready_For_Save() result = save_game.Save(g, cmd, label) if result == None: New_Mail("Game saved.") else: New_Mail(result) if cmd != None: # Back to game. Special_Refresh() current_menu = in_game_menu ui.Reset() if autosave_timer <= cur_time and g.game_running and DEBUG and not menu_inhibit: # Autosave is slow, so it's really a debugging feature. save_game.Save(g, 11, "Autosave") autosave_timer = cur_time + 60 if (g.historian_time <= cur_time) and (g.game_running) and (not menu_inhibit): g.historian.append(review.Analyse_Network(g)) g.historian_time = cur_time + 4 tutor.Off() # About to exit. Blackout. screen.fill((0, 0, 0)) if (stats_review): review.Review(screen, (width, height), g, g.historian) return quit
current_menu.Draw(screen) alarm_sound.Set(0.0) stats_back = (0, 0, 0) supply = g.net.hub.Get_Steam_Supply() demand = g.net.hub.Get_Steam_Demand() if (g.net.hub.Get_Pressure() < PRESSURE_DANGER): # You'll lose the game if you stay in this zone # for longer than a timeout. Also, an # alarm will sound. if (g.game_ends_at == None): sound.FX("steamcrit") g.warning_given = True New_Mail("Danger! The City needs more steam!", (255, 0, 0)) g.game_ends_at = cur_time + DIFFICULTY.GRACE_TIME New_Mail( "Game will end on Day %u unless supplies are increased." % (int(g.game_ends_at)), (255, 0, 0)) if (flash): demand_colour = (255, 0, 0) if (not menu_inhibit): alarm_sound.Set(0.6) else: demand_colour = (128, 0, 0) stats_back = (100, 0, 0) elif (g.net.hub.Get_Pressure() < PRESSURE_WARNING):
def Main_Loop(restore_pos): global game # Initialisation of screen things. (width, height) = screen.Update_Resolution() menu_margin = height screen.surface.fill(BLACK) pygame.display.flip() tutor.Off() draw_obj.Flush_Draw_Obj_Cache() # in case of resize # Grid setup (w, h) = GRID_SIZE assert w == h Set_Grid_Size(height / h) # Right-hand side windows are removed game_screen_rect = Rect(SCROLL_MARGIN, SCROLL_MARGIN, width - (SCROLL_MARGIN * 2), height - (SCROLL_MARGIN * 2)) game_screen_surf = screen.surface.subsurface(game_screen_rect) menu_button_rect = Rect(0, 0, SCROLL_MARGIN * 3, SCROLL_MARGIN * 3) alarm_sound = sound.Persisting_Sound("emergency") # UI setup ui = User_Interface(game.net, (width, height), game.bg_number) exit_options = [(MENU_MENU, "Exit to Main Menu", []), (MENU_QUIT, "Exit to " + extra.Get_OS(), [K_F10])] save_available = [(MENU_SAVE, "Save Game", []), (MENU_LOAD, "Restore Game", []), (None, None, [])] if (game.challenge == MENU_TUTORIAL): save_available = [] in_game_menu = menu.Menu([(None, None, []), (MENU_MUTE, "Toggle Sound", []), (None, None, [])] + save_available + [(MENU_HIDE, "Return to Game", [K_ESCAPE])] + exit_options) current_menu = in_game_menu flash = True quit_state = MENU_LOOP_RUN in_game_menu.Select(None) mail.Initialise() autosave_timer = 0 DIFFICULTY.Set(game.challenge) def Summary(): lev = dict() lev[MENU_TUTORIAL] = "a Tutorial" lev[MENU_BEGINNER] = "a Beginner" lev[MENU_INTERMEDIATE] = "an Intermediate" lev[MENU_EXPERT] = "an Expert" assert game.challenge != None assert lev.has_key(game.challenge) New_Mail("You are playing " + lev[game.challenge] + " game.") # Almost ready to start... but are we starting # from a savegame? def Restore(cmd): global game (g2, result) = save_game.Load(game, cmd) if (result == None): game = g2 ui.net = game.net mail.Initialise() assert game.challenge != None DIFFICULTY.Set(game.challenge) New_Mail("Game restored. It is the " + game.season_fx.name + " season.") else: New_Mail(result) if (restore_pos != None): game.challenge = MENU_INTERMEDIATE Restore(restore_pos) assert game.challenge != None Summary() if (game.challenge == MENU_TUTORIAL): tutor.On((menu_margin * 40) / 100) # In Game - Main loop while (quit_state == MENU_LOOP_RUN): if (game.game_running): flash = not flash draw_obj.Next_Frame() # Flashing lights on the various items ui.Draw_Game(game_screen_surf, game.season_fx) pygame.draw.rect(screen.surface, CYAN, menu_button_rect) game.season_fx.Per_Frame(1) ui.Frame_Advance() game.net.Compute() pygame.display.flip() screen.clock.tick(FRAME_RATE) # Events e = screen.Get_Event(False) while (e.type != NOEVENT): if e.type == QUIT: quit_state = MENU_QUIT break elif e.type == VIDEORESIZE: quit_state = MENU_RESIZE_EVENT elif ((e.type == MOUSEBUTTONDOWN) and (e.button == BUTTON_LEFT)): # Left mouse down (x, y) = e.pos if menu_button_rect.collidepoint(e.pos): # on menu button quit_state = MENU_MENU elif game_screen_rect.collidepoint(e.pos): # on game window ui.Game_Mouse_Down( (x - game_screen_rect.left, y - game_screen_rect.top)) else: # on scrollbar pass elif (e.type == MOUSEMOTION): (x, y) = e.pos ui.Game_Mouse_Move( (x - game_screen_rect.left, y - game_screen_rect.top)) elif ((e.type == MOUSEBUTTONUP) and (e.button == BUTTON_LEFT)): (x, y) = e.pos ui.Game_Mouse_Up( (x - game_screen_rect.left, y - game_screen_rect.top)) elif e.type == KEYDOWN: ui.Key_Press(e.key) elif ((e.type == MOUSEBUTTONDOWN) and (e.button != BUTTON_LEFT)): ui.Right_Mouse_Down() e = screen.Get_Event(False) tutor.Off() alarm_sound.Set(0.0) if quit_state != MENU_MENU: return quit_state # In Game - Menu quit_state = MENU_LOOP_RUN while quit_state == MENU_LOOP_RUN: current_menu.Draw(screen.surface) pygame.display.flip() screen.clock.tick(FRAME_RATE) # Events e = screen.Get_Event(True) while (e.type != NOEVENT): if e.type == QUIT: quit_state = MENU_QUIT break elif e.type == VIDEORESIZE: quit_state = MENU_RESIZE_EVENT elif ((e.type == MOUSEBUTTONDOWN) and (e.button == BUTTON_LEFT)): current_menu.Mouse_Down(e.pos) elif e.type == MOUSEMOTION: current_menu.Mouse_Move(e.pos) elif e.type == KEYDOWN: current_menu.Key_Press(e.key) e = screen.Get_Event(False) cmd = current_menu.Get_Command() current_menu.Select(None) # consume command if (current_menu == in_game_menu): # It's the normal menu. if (cmd == MENU_QUIT): quit_state = MENU_QUIT ui.Reset() # makes menu disappear elif (cmd == MENU_MENU): quit_state = MENU_MENU ui.Reset() elif (cmd == MENU_SAVE): if (game.game_running): # Switch to alternate menu current_menu = save_menu.Save_Menu(True) elif (cmd == MENU_LOAD): current_menu = save_menu.Save_Menu(False) elif (cmd == MENU_REVIEW): quit_state = MENU_REVIEW ui.Reset() elif (cmd != None): # Default option - back to game if (not game.game_running): New_Mail("Sorry - the game has finished") ui.Reset() else: # It's another menu! That means it's the save menu. if ((cmd != None) and (cmd >= 0)): if (not current_menu.Is_Saving()): Restore(cmd) else: label = "%s season - %s" % (game.season_fx.name, time.asctime()) game.net.Make_Ready_For_Save() result = save_game.Save(game, cmd, label) if (result == None): New_Mail("Game saved.") else: New_Mail(result) if (cmd != None): # Back to game. Special_Refresh() current_menu = in_game_menu ui.Reset() return quit_state