diff --git a/src/actions.hpp b/src/actions.hpp index 1e6c1a3bfce..6daac0b6df4 100644 --- a/src/actions.hpp +++ b/src/actions.hpp @@ -10,6 +10,7 @@ See the COPYING file for more details. */ + #ifndef ACTIONS_H_INCLUDED #define ACTIONS_H_INCLUDED @@ -24,11 +25,26 @@ #include #include -std::string recruit_unit(const gamemap& map, int team, - std::map& units, - unit& unit, gamemap::location preferred_location, +//this file defines various functions which implement different in-game +//events and commands. + +//recruit_unit: function which recruits a unit into the game. A +//copy of u will be created and inserted as the new recruited unit. +//If need_castle is true, then the new unit must be on the same castle +//as the leader of the team is on the keep of. +// +//If preferred_location is in a valid location, it will be used, otherwise +//a valid location will be arbitrarily chosen. If disp is not NULL, the +//new unit will be faded in. +// +//If the unit cannot be recruited, then a human-readable message +//describing why not will be returned. On success, the return string is empty +std::string recruit_unit(const gamemap& map, int team, unit_map& units, + unit& u, gamemap::location preferred_location, display *disp=NULL, bool need_castle=true); +//a structure which defines all the statistics for a potential +//battle that could take place. struct battle_stats { std::string attack_name, defend_name; @@ -43,6 +59,19 @@ struct battle_stats bool attacker_plague, defender_plague; }; +//evaluate_battle_stats: a function which, if given an attacker +//and defender, and the number of a weapon to use, will report +//the statistics if that battle were to take place. +// +//attacker_terrain_override allows a different terrain to the +//one currently stood on by the attacker to be used in calculating +//the statistics. This is useful if one wants to look at the +//statistics if an attacker were to attack from one of several +//different locations. +// +//if include_strings is false, then none of the strings in +//battle_stats will be populated, and the function will run +//substantially faster. battle_stats evaluate_battle_stats( const gamemap& map, const gamemap::location& attacker, @@ -54,6 +83,7 @@ battle_stats evaluate_battle_stats( gamemap::TERRAIN attacker_terrain_override=0, bool include_strings=true); +//attack: executes an attack. void attack(display& gui, const gamemap& map, const gamemap::location& attacker, const gamemap::location& defender, @@ -62,42 +92,62 @@ void attack(display& gui, const gamemap& map, const gamestatus& state, const game_data& info, bool player_is_attacker); +//given the location of a village, will return the 0-based index of the team +//that currently owns it, and -1 if it is unowned. int tower_owner(const gamemap::location& loc, std::vector& teams); +//makes it so the tower at the given location is owned by the given +//0-based team number void get_tower(const gamemap::location& loc, std::vector& teams, int team_num); +//given the 1-based side, will find the leader of that side, +//and return an iterator to the leader std::map::iterator find_leader(std::map& units, int side); +//calculates healing for all units for the given side. Should be called +//at the beginning of a side's turn. void calculate_healing(display& disp, const gamemap& map, std::map& units, int side); +//function which, given the location of a unit that is advancing, and the +//name of the unit it is advancing to, will return the advanced version of +//this unit. (with traits and items retained). unit get_advanced_unit(const game_data& info, std::map& units, const gamemap::location& loc, const std::string& advance_to); +//function which will advance the unit at loc to 'advance_to'. void advance_unit(const game_data& info, std::map& units, const gamemap::location& loc, const std::string& advance_to); +//function which returns true iff the unit at loc is currently affected +//by leadership. (i.e. has a higher-level 'leadership' unit next to it) bool under_leadership(const std::map& units, const gamemap::location& loc); +//checks to see if a side has won, and will throw an end_level_exception +//if one has. void check_victory(std::map& units, const std::vector& teams); //gets the time of day at a certain tile. Certain tiles may have a time of -//day that differs from 'the' time of day, if a unit that brings light is there +//day that differs from 'the' time of day, if a unit that illuminates is +//in that tile or adjacent. const time_of_day& timeofday_at(const gamestatus& status, const std::map& units, const gamemap::location& loc); +//returns the amount that a unit's damage should be multiplied by due to +//the current time of day. double combat_modifier(const gamestatus& status, const std::map& units, const gamemap::location& loc, unit_type::ALIGNMENT alignment); +//structure which records information to be able to undo a movement struct undo_action { undo_action(const std::vector& rt,int sm,int orig=-1) : route(rt), starting_moves(sm), original_village_owner(orig) {} @@ -108,14 +158,22 @@ struct undo_action { typedef std::deque undo_list; +//function which moves a unit along the sequence of locations given by +//steps. If the unit cannot make it completely along the path this turn, +//a goto order will be set. If move_recorder is not NULL, the move will +//be recorded in it. If undos is not NULL, undo information will be added. size_t move_unit(display* disp, const gamemap& map, unit_map& units, std::vector& teams, const std::vector& steps, replay* move_recorder, undo_list* undos); +//function which will clear shroud away for the given 0-based team based on +//current unit positions. Returns true if some shroud is actually cleared away. bool clear_shroud(display& disp, const gamemap& map, const game_data& gamedata, const unit_map& units, std::vector& teams, int team); +//will return true iff the unit at 'loc' has any possible moves it can do +//(including attacking etc). bool unit_can_move(const gamemap::location& loc, const unit_map& units, const gamemap& map, const std::vector& teams); diff --git a/src/display.cpp b/src/display.cpp index 92a446eb2f1..8d5bd53542f 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -2306,7 +2306,7 @@ bool display::update_locked() const bool display::turbo() const { bool res = turbo_; - if(keys_[KEY_LSHIFT] || keys_[KEY_RSHIFT]) + if(keys_[SDLK_LSHIFT] || keys_[SDLK_RSHIFT]) res = !res; return res; diff --git a/src/display.hpp b/src/display.hpp index 630c4aba011..0d6f76a286d 100644 --- a/src/display.hpp +++ b/src/display.hpp @@ -28,6 +28,19 @@ #include #include +//display: class which takes care of displaying the map and +//game-data on the screen. +// +//the display is divided into two main sections: the game area, +//which displays the tiles of the game board, and units on them, +//and the side bar, which appears on the right hand side. The side bar +//display is divided into three sections: +// - the minimap, which is displayed at the top right +// - the game status, which includes the day/night image, the turn number, +// information about the current side, and information about the hex +// currently moused over (highlighted) +// - the unit status, which displays an image for, and stats for, the +// current unit. class display { public: @@ -39,88 +52,190 @@ public: const std::vector& t); ~display(); + //new_turn should be called on every new turn, to update + //lighting settings. void new_turn(); + + //function to make it so a unit is 'hidden' - not displayed + //when the tile it is on is drawn. Only one unit may be hidden + //at a time. The previously hidden unit will be returned. gamemap::location hide_unit(const gamemap::location& loc); + //function which given rgb values, will return the equivalent pixel + //for the frame buffer surface. Pixel rgb(int r, int g, int b) const; + //function which scrolls the display by xmov,ymov. Invalidation and + //redrawing will be scheduled. void scroll(double xmov, double ymov); + + //function which zooms the display by the specified amount. Negative + //valeus zoom out. void zoom(double amount); + + //function to take the zoom amount to the default. void default_zoom(); enum SCROLL_TYPE { SCROLL, WARP }; + + //function which will scroll such that location x,y is on-screen. void scroll_to_tile(int x, int y, SCROLL_TYPE scroll_type=SCROLL); + + //function which will scroll such that location x1,y1 is on-screen. + //it will also try to make it such that x2,y2 is on-screen but this + //is not guaranteed. void scroll_to_tiles(int x1, int y1, int x2, int y2, SCROLL_TYPE scroll_type=SCROLL); + //invalidates entire screen, including all tiles and sidebar. void redraw_everything(); + + //draws invalidated items. If update is true, will also copy the + //display to the frame buffer. If force is true, will not skip frames, + //even if running behind. void draw(bool update=true,bool force=false); + //the dimensions of the display. x and y are width/height. mapx is the + //width of the portion of the display which shows the game area. Between + //mapx and x is the sidebar region. int x() const; int mapx() const; int y() const; + SDL_Rect screen_area() const; + //function to display a location as selected. If a unit is in the location, + //and there is no unit in the currently highlighted hex, the unit will be + //displayed in the sidebar. void select_hex(gamemap::location hex); + + //function to highlight a location. If a unit is in the location, it will + //be displayed in the sidebar. Selection is used when a unit has been + //clicked on, while highlighting is used when a location has been moused + //over void highlight_hex(gamemap::location hex); + + //given x,y co-ordinates of the mouse, will return the location of the + //hex that the mouse is currently over. Returns an invalid location is + //the mouse isn't over any valid location. gamemap::location hex_clicked_on(int x, int y); + + //given x,y co-ordinates of the mouse, will return the location of the + //hex in the minimap that the mouse is currently over, or an invalid + //location if the mouse isn't over the minimap. gamemap::location minimap_location_on(int x, int y); + //sets the paths that are currently displayed as available for the unit + //to move along. All other paths will be greyed out. If NULL, no paths + //will be displayed as selected. //paths_list must remain valid until it is set again void set_paths(const paths* paths_list); + //sets the route along which footsteps are drawn to show movement of a + //unit. If NULL, no route is displayed. //route does not have to remain valid after being set void set_route(const paths::route* route); + //functions to get the on-screen positions of hexes. double get_location_x(const gamemap::location& loc) const; double get_location_y(const gamemap::location& loc) const; + //function to display movement of a unit along the given sequence of tiles void move_unit(const std::vector& path, unit& u); + + //function to show one unit taking one attack attempt at another. damage + //is the amount of damage inflicted, and 0 if the attack misses. bool unit_attack(const gamemap::location& a, const gamemap::location& b, int damage, const attack_type& attack); + + //function to draw the tile at location (x,y). If unit_image is not NULL, + //then it will be used, otherwise the unit's default image will be used. + //alpha controls how faded the unit is. If blend_to is not 0, then the + //unit will be alpha-blended to blend_to instead of the background colour void draw_tile(int x, int y, SDL_Surface* unit_image=NULL, double alpha=1.0, short blend_to=0); + + //function to draw a footstep for the given location, on screen at + //pixel co-ordinates (xloc,yloc). A footstep will only be drawn if + //loc is on the current route set by set_route. Otherwise it will + //return with no effect. void draw_footstep(const gamemap::location& loc, int xloc, int yloc); + //gets the underlying screen object. CVideo& video() { return screen_; } //blits a surface with black as alpha void blit_surface(int x, int y, SDL_Surface* surface); + //function to invalidate all tiles. void invalidate_all(); + + //function to invalidate the game status displayed on the sidebar. void invalidate_game_status(); + + //function to invalidate that unit status displayed on the sidebar. void invalidate_unit(); + //function to schedule the minimap for recalculation. Useful if any + //terrain in the map has changed. void recalculate_minimap(); + //functions to add and remove overlays from locations. An overlay is an + //image that is displayed on top of the tile. One tile may have multiple + //overlays. remove_overlay will remove all overlays on a tile. void add_overlay(const gamemap::location& loc, const std::string& image); void remove_overlay(const gamemap::location& loc); + //function which draws the details of the unit at the given location, at + //(x,y) on-screen. xprofile and yprofile are the size of the unit's image. + //this function is suitable for drawing a unit's details on the sidebar, + //but can also be used to draw the unit details on a dialog elsewhere on + //the screen. void draw_unit_details(int x, int y, const gamemap::location& loc, const unit& u, SDL_Rect& description_rect, int xprofile,int yprofile,SDL_Rect* clip_rect=NULL); + //function which copies the backbuffer to the framebuffer. void update_display(); + //functions used in the editor. void draw_terrain_palette(int x, int y, gamemap::TERRAIN selected); gamemap::TERRAIN get_terrain_on(int palx, int paly, int x, int y); + //set_team sets the team controlled by the player using the computer, + //and it is this team whose data is displayed in the game status. + //set_playing_team sets the team whose turn it currently is void set_team(size_t team); void set_playing_team(size_t team); + //makes it so that the unit at the given location will be displayed + //in an advancing-highlight with intensity between 0.0 and 1.0 given + //by amount. void set_advancing_unit(const gamemap::location& loc, double amount); + //function to stop the screen being redrawn. Anything that happens while + //the update is locked will be hidden from the user's view. + //note that this function is re-entrant, meaning that if lock_updates(true) + //is called twice, lock_updates(false) must be called twice to unlock + //updates. void lock_updates(bool value); bool update_locked() const; + //functions to set/get whether 'turbo' mode is on. When turbo mode is on, + //everything moves much faster. bool turbo() const; void set_turbo(bool turbo); + //function which determines whether a grid should be overlayed on the + //game board to more clearly show where hexes are. void set_grid(bool grid); + //a debug highlight draws a cross on a tile to emphasize something there. + //it is used in debug mode, typically to show AI plans. static void debug_highlight(const gamemap::location& loc, double amount); static void clear_debug_highlights(); + //function which returns true if location (x,y) is covered in shroud. bool shrouded(int x, int y) const; private: @@ -226,6 +341,7 @@ private: static std::map debugHighlights_; }; +//an object which will lock the display for the duration of its lifetime. struct update_locker { update_locker(display& d, bool lock=true) : disp(d), unlock(lock) { diff --git a/src/editor/editor.cpp b/src/editor/editor.cpp index 68cc612fe09..32201bd54b5 100644 --- a/src/editor/editor.cpp +++ b/src/editor/editor.cpp @@ -82,7 +82,7 @@ int main(int argc, char** argv) std::cerr << "starting for(;;)\n"; for(;;) { - if(key[KEY_ESCAPE]) + if(key[SDLK_ESCAPE]) break; int mousex, mousey; @@ -90,25 +90,25 @@ int main(int argc, char** argv) const bool new_left_button = mouse_flags & SDL_BUTTON_LMASK; const bool new_right_button = mouse_flags & SDL_BUTTON_RMASK; - if(key[KEY_UP] || mousey == 0) + if(key[SDLK_UP] || mousey == 0) gui.scroll(0.0,-scroll_speed); - if(key[KEY_DOWN] || mousey == gui.y()-1) + if(key[SDLK_DOWN] || mousey == gui.y()-1) gui.scroll(0.0,scroll_speed); - if(key[KEY_LEFT] || mousex == 0) + if(key[SDLK_LEFT] || mousex == 0) gui.scroll(-scroll_speed,0.0); - if(key[KEY_RIGHT] || mousex == gui.x()-1) + if(key[SDLK_RIGHT] || mousex == gui.x()-1) gui.scroll(scroll_speed,0.0); - if(key[KEY_Z]) + if(key[SDLK_Z]) gui.zoom(zoom_amount); - if(key[KEY_X]) + if(key[SDLK_X]) gui.zoom(-zoom_amount); - if(key[KEY_D]) + if(key[SDLK_D]) gui.default_zoom(); gui.highlight_hex(gui.hex_clicked_on(mousex,mousey)); diff --git a/src/events.hpp b/src/events.hpp index b3b3f8764c3..efbbbcf15a7 100644 --- a/src/events.hpp +++ b/src/events.hpp @@ -5,6 +5,9 @@ namespace events { + +//an object which prevents resizing of the screen occuring during +//its lifetime. struct resize_lock { resize_lock(); ~resize_lock(); @@ -13,7 +16,8 @@ struct resize_lock { //any classes that derive from this class will automatically //receive sdl events through the handle function for their lifetime //note that handlers should *always* be allocated as automatic variables -//(never on the free store or in static memory) +//(never on the free store or in static memory), as the event mechanism +//relies on handlers being created and destroyed in LIFO ordering. class handler { public: @@ -26,6 +30,7 @@ private: const int unicode_; }; +//causes events to be dispatched to all handler objects. void pump(); } diff --git a/src/filesystem.hpp b/src/filesystem.hpp index 15710d5ee0e..acb8d014928 100644 --- a/src/filesystem.hpp +++ b/src/filesystem.hpp @@ -18,15 +18,23 @@ enum FILE_NAME_MODE { ENTIRE_FILE_PATH, FILE_NAME_ONLY }; +//function which populates files with all the files and dirs +//with all the directories in dir. If files or dirs are NULL +//they will not be used. +// +//mode determines whether the entire path or just the filename +//is retrieved. void get_files_in_dir(const std::string& dir, std::vector* files, std::vector* dirs=NULL, FILE_NAME_MODE mode=FILE_NAME_ONLY); +//the location of various important files std::string get_prefs_file(); std::string get_saves_dir(); std::string get_user_data_dir(); +//function which returns true iff the given file is a directory bool is_directory(const std::string& fname); #endif diff --git a/src/font.hpp b/src/font.hpp index fff38eb5e52..667cd24c18a 100644 --- a/src/font.hpp +++ b/src/font.hpp @@ -22,18 +22,37 @@ namespace font { +//object which initializes and destroys structures needed for fonts struct manager { manager(); ~manager(); }; +//function which, given a 1-based side, will return the colour of +//that side. const SDL_Color& get_side_colour(int side); +//various standard colours extern const SDL_Color NORMAL_COLOUR, GOOD_COLOUR, BAD_COLOUR, BLACK_COLOUR, BUTTON_COLOUR; enum MARKUP { USE_MARKUP, NO_MARKUP }; +//function to draw text on the screen. The text will be clipped to area. +//If the text runs outside of area horizontally, an ellipsis will be displayed +//at the end of it. If use_tooltips is true, then text with an ellipsis will +//have a tooltip set for it equivalent to the entire contents of the text. +// +//if use_markup is equal to USE_MARKUP, then some very basic 'markup' will +//be done on the text: +// - any line beginning in # will be displayed in BAD_COLOUR +// - any line beginning in @ will be displayed in GOOD_COLOUR +// - any line beginning in + will be displayed with size increased by 2 +// - any line beginning in - will be displayed with size decreased by 2 +// - any line beginning with 0x0n will be displayed in the colour of side n +// +//a bounding rectangle of the text is returned. If gui is NULL, then the +//text will not be drawn, and a bounding rectangle only will be returned. SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size, const SDL_Color& colour, const std::string& text, int x, int y, SDL_Surface* bg=NULL, diff --git a/src/game_config.hpp b/src/game_config.hpp index bb71b1d13d1..5ae50be4f73 100644 --- a/src/game_config.hpp +++ b/src/game_config.hpp @@ -15,6 +15,7 @@ #include +//basic game configuration information is here. namespace game_config { extern const int unit_cost; diff --git a/src/game_events.hpp b/src/game_events.hpp index 52d46f85bbe..9521b0cd3ed 100644 --- a/src/game_events.hpp +++ b/src/game_events.hpp @@ -23,24 +23,34 @@ #include +//this file defines the game's events mechanism. Events might be units +//moving or fighting, or when victory or defeat occurs. A scenario's +//configuration file will define actions to take when certain events +//occur. This module is responsible for making sure that when the events +//occur, the actions take place. +// +//note that game events have nothing to do with SDL events, like mouse +//movement, keyboard events, etc. See events.hpp for how they are handled. namespace game_events { -bool conditional_passed(game_state& state_of_game, - const std::map* units, - config& cond); - +//the game event manager loads the scenario configuration object, and +//ensures that events are handled according to the scenario configuration +//for its lifetime. +// +//thus, a manager object should be created when a scenario is played, and +//destroyed at the end of the scenario. struct manager { - manager(config& cfg, display& disp, gamemap& map, + //note that references will be maintained, and must remain valid + //for the life of the object. + manager(config& scenario_cfg, display& disp, gamemap& map, std::map& units, std::vector& teams, game_state& state_of_game, game_data& data); ~manager(); }; -void raise(const std::string& event, - const gamemap::location& loc1=gamemap::location::null_location, - const gamemap::location& loc2=gamemap::location::null_location); - +//function to fire an event. Events may have up to two arguments, both of +//which must be locations. bool fire(const std::string& event, const gamemap::location& loc1=gamemap::location::null_location, const gamemap::location& loc2=gamemap::location::null_location); diff --git a/src/gamestatus.hpp b/src/gamestatus.hpp index fa8bdaee203..8c4566b5c9f 100644 --- a/src/gamestatus.hpp +++ b/src/gamestatus.hpp @@ -19,16 +19,26 @@ #include #include +//an object which defines the current time of day struct time_of_day { explicit time_of_day(config& cfg); + //the % bonus lawful units receive. chaotic units will + //receive -lawful_bonus. int lawful_bonus; + + //the image to be displayed in the game status. std::string image; std::string name; + + //the colour modifications that should + //be made to the game board to reflect the time of day. int red, green, blue; }; +//class which contains the global status of the game -- namely +//the current turn, the number of turns, and the time of day. class gamestatus { public: @@ -38,8 +48,11 @@ public: size_t turn() const; size_t number_of_turns() const; + //function to move to the next turn. Returns true iff time + //has expired. bool next_turn(); + //an exception object used when loading a game fails. struct load_game_failed { load_game_failed() {} load_game_failed(const std::string& msg) : message(msg) {} @@ -47,6 +60,8 @@ public: std::string message; }; + //an exception object used for any general game error. + //e.g. data files are corrupt. struct game_error { game_error(const std::string& msg) : message(msg) {} std::string message; @@ -59,24 +74,35 @@ private: size_t numTurns_; }; +//object which holds all the data needed to start a scenario. +//i.e. this is the object serialized to disk when saving/loading a game. +//is also the object which needs to be created to start a nwe game struct game_state { game_state() : gold(-1), difficulty("NORMAL") {} - std::string label; - std::string version; - std::string campaign_type; - std::string scenario; - int gold; - std::vector available_units; - std::map variables; - std::string difficulty; + std::string label; //name of the game (e.g. name of save file) + std::string version; //version game was created with. + std::string campaign_type; //type of the game - campaign, multiplayer etc + std::string scenario; //the scenario being played + int gold; //amount of gold the player has saved + std::vector available_units; //units the player has to recall + std::map variables; //variables that have been set + std::string difficulty; //the difficulty level the game is being played on. + //if the game is saved mid-level, we have a series of replay steps to + //take the game up to the position it was saved at. config replay_data; + + //information about the starting conditions of the scenario. Used in + //multiplayer games, when the starting position isn't just literally + //read from a file, since there is game setup information. config starting_pos; }; +//function to get a list of available saves. std::vector get_saves_list(); +//functions to load/save games. void load_game(game_data& data, const std::string& name, game_state& state); void save_game(const game_state& state); diff --git a/src/hotkeys.hpp b/src/hotkeys.hpp index dc0f5093b5b..600ce023b78 100644 --- a/src/hotkeys.hpp +++ b/src/hotkeys.hpp @@ -18,7 +18,26 @@ #include "events.hpp" #include "key.hpp" +//the hotkey system allows hotkey definitions to be loaded from +//configuration objects, and then detect if a keyboard event +//refers to a hotkey command being executed. namespace hotkey { + +//function to load a hotkey configuration object. hotkey configuration objects +//are a list of nodes that look like: +//[hotkey] +//command='cmd' +//key='k' +//ctrl=(yes|no) +//alt=(yes|no) +//shift=(yes|no) +//[/hotkey] +//where 'cmd' is a command name, and 'k' is a key. see hotkeys.cpp for the +//valid command names. +void add_hotkeys(config& cfg); + +//abstract base class for objects that implement the ability +//to execute hotkey commands. class command_executor { public: @@ -38,6 +57,13 @@ public: virtual void recruit() = 0; }; +//function to be called every time a key event is intercepted. Will +//call the relevant function in executor if the keyboard event is +//not NULL. Also handles some events in the function itself, and so +//is still meaningful to call with executor=NULL +void key_event(display& disp, const SDL_KeyboardEvent& event, + command_executor* executor); + //object which will ensure that basic keyboard events like escape //are handled properly for the duration of its lifetime struct basic_handler : public events::handler { @@ -49,11 +75,6 @@ private: display& disp_; }; -void add_hotkeys(config& cfg); - -void key_event(display& disp, const SDL_KeyboardEvent& event, - command_executor* executor); - } #endif diff --git a/src/image.hpp b/src/image.hpp index 1d4ebb8a936..5b17c45200b 100644 --- a/src/image.hpp +++ b/src/image.hpp @@ -7,20 +7,49 @@ #include +//this module manages the cache of images. With an image name, you can get +//the surface corresponding to that image, and don't need to free the image. +//Note that surfaces returned from here are invalidated whenever events::pump() +//is called, and so shouldn't be kept, but should be regotten from here as +//needed. +// +//images come in a number of varieties: +// - unscaled: no modifications have been done on the image. +// - scaled: images are scaled to the size of a tile +// - greyed: images are scaled and in greyscale +// - brightened: images are scaled and brighter than normal. namespace image { + //the image manager is responsible for setting up images, and destroying + //all images when the program exits. It should probably + //be created once for the life of the program struct manager { manager(); ~manager(); }; + //will make all scaled images have these rgb values added to all + //their pixels. i.e. add a certain colour hint to images. useful + //for representing day/night. Invalidates all scaled images. void set_colour_adjustment(int r, int g, int b); + + //sets the pixel format used by the images. Is called every time the + //video mode changes. Invalidates all images. void set_pixel_format(SDL_PixelFormat* format); + + //sets the amount scaled images should be scaled. Invalidates all + //scaled images. void set_zoom(double zoom); enum TYPE { UNSCALED, SCALED, GREYED, BRIGHTENED }; + + //function to get the surface corresponding to an image. SDL_Surface* get_image(const std::string& filename,TYPE type=SCALED); + + //function to get a scaled image, but scale it to specific dimensions. + //if you later try to get the same image using get_image() the image will + //have the dimensions specified here. SDL_Surface* get_image_dim(const std::string& filename, size_t x, size_t y); } diff --git a/src/intro.cpp b/src/intro.cpp index 3b478a9530c..ca1ed8e5b48 100644 --- a/src/intro.cpp +++ b/src/intro.cpp @@ -114,11 +114,11 @@ void show_intro(display& screen, config& data) events::pump(); - if(key[KEY_ESCAPE] || + if(key[SDLK_ESCAPE] || skip_button.process(mousex,mousey,left_button)) return; - if(key[KEY_SPACE] || key[KEY_ENTER] || + if(key[SDLK_SPACE] || key[SDLK_RETURN] || next_button.process(mousex,mousey,left_button)) { if(!last) break; @@ -217,7 +217,7 @@ void show_map_scene(display& screen, config& data) update_rect(dstrect); for(int i = 0; i != 50; ++i) { - if(key[KEY_ESCAPE]) { + if(key[SDLK_ESCAPE]) { break; } @@ -227,19 +227,19 @@ void show_map_scene(display& screen, config& data) int a, b; const int mouse_flags = SDL_GetMouseState(&a,&b); - if(key[KEY_ENTER] || key[KEY_SPACE] || mouse_flags) { + if(key[SDLK_RETURN] || key[SDLK_SPACE] || mouse_flags) { break; } } - if(key[KEY_ESCAPE]) { + if(key[SDLK_ESCAPE]) { break; } screen.video().flip(); } - if(!key[KEY_ESCAPE]) { + if(!key[SDLK_ESCAPE]) { SDL_Delay(500); } @@ -258,8 +258,8 @@ void show_map_scene(display& screen, config& data) int a, b; const int mouse_flags = SDL_GetMouseState(&a,&b); - const bool new_state = mouse_flags || key[KEY_ESCAPE] || - key[KEY_ENTER] || key[KEY_SPACE]; + const bool new_state = mouse_flags || key[SDLK_ESCAPE] || + key[SDLK_RETURN] || key[SDLK_SPACE]; if(new_state && !last_state) break; diff --git a/src/intro.hpp b/src/intro.hpp index 975f9d91814..e7606d6ac73 100644 --- a/src/intro.hpp +++ b/src/intro.hpp @@ -19,8 +19,35 @@ #include +//function to show an introduction sequence specified by data. +//the format of data is like, +//[part] +//id='id' +//story='story' +//image='img' +//[/part] +//where 'id' is a unique identifier, 'story' is text describing +//storyline, and 'img' is an image. +// +//each part of the sequence will be displayed in turn, with the +//user able to go to the next part, or skip it entirely. void show_intro(display& screen, config& data); +//function to show the map before each scenario. +//data is in a format that looks like, +//[bigmap] +//image='map-image' +// [dot] +// x='x' +// y='y' +// type=cross (optional) +// [/dot] +// ... more 'dot' nodes' +//[/bigmap] +// +//where 'map-image' is the image of the map. dots are displayed +//at 'x','y' on the image in sequence. type=cross should be used +//for the last dot, to show where the battle takes place. void show_map_scene(display& screen, config& data); #endif diff --git a/src/key.cpp b/src/key.cpp index 7221acf0252..2df03cc43d7 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -27,7 +27,7 @@ int main( void ) for(;;) { if( key[KEY_RETURN] != 0 ) printf( "key(ENTER) pressed\n" ); - if( key[KEY_ESCAPE] != 0 ) + if( key[SDLK_ESCAPE] != 0 ) return 1; } } @@ -42,7 +42,7 @@ CKey::CKey() : is_enabled(true) int CKey::operator[]( int code ) { - return (code == KEY_ESCAPE || is_enabled) && int(key_list[code]); + return (code == SDLK_ESCAPE || is_enabled) && int(key_list[code]); } void CKey::SetEnabled( bool enable ) diff --git a/src/key.hpp b/src/key.hpp index 73b024fc8b8..8445fa2a645 100644 --- a/src/key.hpp +++ b/src/key.hpp @@ -10,87 +10,26 @@ See the COPYING file for more details. */ + #ifndef KEY_HPP_INCLUDED #define KEY_HPP_INCLUDED #include "SDL.h" +//object which keeps track of all the keys on the keyboard, and +//whether any key is pressed or not can be found by using its +//operator[]. Note though that it is generally better to use +//key events to see when keys are pressed rather than poll using +//this object. class CKey { - public: +public: CKey(); int operator[](int); void SetEnabled(bool enable); - private: +private: Uint8 *key_list; bool is_enabled; }; -#define KEY_PAGEUP SDLK_PAGEUP -#define KEY_PAGEDOWN SDLK_PAGEDOWN -#define KEY_BACKSPACE SDLK_BACKSPACE -#define KEY_DELETE SDLK_DELETE -#define KEY_TAB SDLK_TAB -#define KEY_CLEAR SDLK_CLEAR -#define KEY_RETURN SDLK_RETURN -#define KEY_ENTER KEY_RETURN -#define KEY_ESCAPE SDLK_ESCAPE -#define KEY_SPACE SDLK_SPACE -#define KEY_0 SDLK_0 -#define KEY_1 SDLK_1 -#define KEY_2 SDLK_2 -#define KEY_3 SDLK_3 -#define KEY_4 SDLK_4 -#define KEY_5 SDLK_5 -#define KEY_6 SDLK_6 -#define KEY_7 SDLK_7 -#define KEY_8 SDLK_8 -#define KEY_9 SDLK_9 -#define KEY_KP0 SDLK_KP0 -#define KEY_KP1 SDLK_KP1 -#define KEY_KP2 SDLK_KP2 -#define KEY_KP3 SDLK_KP3 -#define KEY_KP4 SDLK_KP4 -#define KEY_KP5 SDLK_KP5 -#define KEY_KP6 SDLK_KP6 -#define KEY_KP7 SDLK_KP7 -#define KEY_KP8 SDLK_KP8 -#define KEY_KP9 SDLK_KP9 -#define KEY_A SDLK_a -#define KEY_B SDLK_b -#define KEY_C SDLK_c -#define KEY_D SDLK_d -#define KEY_E SDLK_e -#define KEY_F SDLK_f -#define KEY_G SDLK_g -#define KEY_H SDLK_h -#define KEY_I SDLK_i -#define KEY_J SDLK_j -#define KEY_K SDLK_k -#define KEY_L SDLK_l -#define KEY_M SDLK_m -#define KEY_N SDLK_n -#define KEY_O SDLK_o -#define KEY_P SDLK_p -#define KEY_Q SDLK_q -#define KEY_R SDLK_r -#define KEY_S SDLK_s -#define KEY_T SDLK_t -#define KEY_U SDLK_u -#define KEY_V SDLK_v -#define KEY_W SDLK_w -#define KEY_X SDLK_x -#define KEY_Y SDLK_y -#define KEY_Z SDLK_z -#define KEY_RSHIFT SDLK_RSHIFT -#define KEY_LSHIFT SDLK_LSHIFT -#define KEY_RCONTROL SDLK_RCTRL -#define KEY_LCONTROL SDLK_LCTRL -#define KEY_RALT SDLK_RALT -#define KEY_LALT SDLK_LALT -#define KEY_UP SDLK_UP -#define KEY_DOWN SDLK_DOWN -#define KEY_LEFT SDLK_LEFT -#define KEY_RIGHT SDLK_RIGHT - #endif diff --git a/src/language.hpp b/src/language.hpp index f7f6e91c2ab..c31d3c43ce7 100644 --- a/src/language.hpp +++ b/src/language.hpp @@ -19,13 +19,29 @@ #include #include +//this module controls internationalization. + +//table of strings which are displayed to the user. Maps ids -> text. +//this table should be consulted whenever something is to be +//displayed on screen. extern std::map string_table; +//function which, given the main configuration object, will return +//a list of the translations of the game available. std::vector get_languages(config& cfg); + +//function which, given the main configuration object, and a locale, +//will set string_table to be populated with data from that locale. +//locale may be either the full name of the language, like 'English', +//or the 2-letter version, like 'en'. bool set_language(const std::string& locale, config& cfg); +//function which attempts to query and return the locale on the system std::string get_locale(); +//two character sets are supported: LATIN1 and UTF-8. This is +//set in the translation by using encoding=(LATIN1|UTF-8) +//the character set used affects the font rendering function called enum CHARSET { CHARSET_LATIN1, CHARSET_UTF8 }; CHARSET charset(); diff --git a/src/map.hpp b/src/map.hpp index f0caf550516..abc539fe7e4 100644 --- a/src/map.hpp +++ b/src/map.hpp @@ -10,6 +10,7 @@ See the COPYING file for more details. */ + #ifndef MAP_H_INCLUDED #define MAP_H_INCLUDED @@ -20,12 +21,18 @@ #include #include +//class which encapsulates the map of the game. Although the game is hexagonal, +//the map is stored as a grid. Each type of terrain is represented by a letter. class gamemap { public: typedef char TERRAIN; + //some types of terrain which must be known, and can't just be loaded + //in dynamically because they're special. It's asserted that there will + //be corresponding entries for these types of terrain in the terrain + //configuration file. enum { VOID_TERRAIN = ' ', CASTLE = 'C', TOWER = 't', FOREST = 'f' }; //the name of the terrain is the terrain itself, the underlying terrain @@ -36,12 +43,15 @@ public: const std::string& underlying_terrain_name(TERRAIN terrain) const; TERRAIN underlying_terrain(TERRAIN terrain) const; + //exception thrown if the map file is not in the correct format. struct incorrect_format_exception { incorrect_format_exception(const char* msg) : msg_(msg) {} const char* const msg_; }; + //structure which represents a location on the map. struct location { + //any valid direction which can be moved in in our hexagonal world. enum DIRECTION { NORTH, NORTH_EAST, SOUTH_EAST, SOUTH, SOUTH_WEST, NORTH_WEST }; @@ -62,36 +72,52 @@ public: static location null_location; }; - gamemap(config& cfg, + //loads a map, with the given terrain configuration. + //data should be a series of lines, with each character representing + //one hex on the map. Starting locations are represented by numbers, + //and will be of type keep. + gamemap(config& terrain_cfg, const std::string& data); //throw(incorrect_format_exception) std::string write() const; + //dimensions of the map. int x() const; int y() const; + //allows lookup of terrain at a particular location. const std::vector& operator[](int index) const; - const location& starting_position(int n) const; + //functions to manipulate starting positions of the different sides. + const location& starting_position(int side) const; int num_starting_positions() const; bool is_starting_position(const location& loc) const; + //function which, given a location, will tell if that location is + //on the map. Should be called before indexing using [] bool on_board(const location& loc) const { return loc.valid() && loc.x < x() && loc.y < y(); } + //function to tell if the map is of 0 size. bool empty() const { return x() == 0 || y() == 0; } + //function to return a list of the locations of villages on the map const std::vector& towers() const { return towers_; } + //function to get the corresponding terrain_type information object + //for a given type of terrain const terrain_type& get_terrain_info(TERRAIN terrain) const; + //gets the list of which terrain types should display on top of + //other terrain types. Has no effect on gameplay, only display. const std::vector& get_terrain_precedence() const; + //clobbers over the terrain at location 'loc', with the given terrain void set_terrain(const location& loc, TERRAIN ter); private: std::vector terrainPrecedence_; diff --git a/src/mapeditor/editor.cpp b/src/mapeditor/editor.cpp index d02562e364f..6918029cc83 100644 --- a/src/mapeditor/editor.cpp +++ b/src/mapeditor/editor.cpp @@ -83,7 +83,7 @@ int main(int argc, char** argv) std::cerr << "starting for(;;)\n"; for(;;) { - if(key[KEY_ESCAPE]) + if(key[SDLK_ESCAPE]) break; int mousex, mousey; @@ -91,25 +91,25 @@ int main(int argc, char** argv) const bool new_left_button = mouse_flags & SDL_BUTTON_LMASK; const bool new_right_button = mouse_flags & SDL_BUTTON_RMASK; - if(key[KEY_UP] || mousey == 0) + if(key[SDLK_UP] || mousey == 0) gui.scroll(0.0,-scroll_speed); - if(key[KEY_DOWN] || mousey == gui.y()-1) + if(key[SDLK_DOWN] || mousey == gui.y()-1) gui.scroll(0.0,scroll_speed); - if(key[KEY_LEFT] || mousex == 0) + if(key[SDLK_LEFT] || mousex == 0) gui.scroll(-scroll_speed,0.0); - if(key[KEY_RIGHT] || mousex == gui.x()-1) + if(key[SDLK_RIGHT] || mousex == gui.x()-1) gui.scroll(scroll_speed,0.0); - if(key[KEY_Z]) + if(key[SDLK_Z]) gui.zoom(zoom_amount); - if(key[KEY_X]) + if(key[SDLK_X]) gui.zoom(-zoom_amount); - if(key[KEY_D]) + if(key[SDLK_D]) gui.default_zoom(); gui.highlight_hex(gui.hex_clicked_on(mousex,mousey)); diff --git a/src/multiplayer.hpp b/src/multiplayer.hpp index 9862e79d289..75aad17f564 100644 --- a/src/multiplayer.hpp +++ b/src/multiplayer.hpp @@ -19,13 +19,17 @@ #include "unit_types.hpp" #include "video.hpp" +//an object which guarantees that when it is destroyed, a 'leave game' +//message will be sent to any hosts still connected. struct network_game_manager { + network_game_manager() {} ~network_game_manager(); }; -void play_multiplayer_client(display& disp, game_data& units_data, - config& cfg, game_state& state); - +//function to host a multiplayer game. If server is true, then the +//game will accept connections from foreign hosts. Otherwise it'll +//just use existing network connections for players, or the game +//is an entirely local game void play_multiplayer(display& disp, game_data& units_data, config cfg, game_state& state, bool server=true); diff --git a/src/multiplayer_client.hpp b/src/multiplayer_client.hpp index 49c2e3e582e..86e6975a165 100644 --- a/src/multiplayer_client.hpp +++ b/src/multiplayer_client.hpp @@ -7,6 +7,8 @@ #include "network.hpp" #include "unit_types.hpp" +//function to play a game as a client, joining either another player who is +//hosting a game, or connecting to a server. void play_multiplayer_client(display& disp, game_data& units_data, config& cfg, game_state& state); diff --git a/src/multiplayer_lobby.cpp b/src/multiplayer_lobby.cpp index 71dbb155cad..df965d126ef 100644 --- a/src/multiplayer_lobby.cpp +++ b/src/multiplayer_lobby.cpp @@ -145,8 +145,8 @@ RESULT enter(display& disp, config& game_data) break; } - const bool enter = key[KEY_ENTER] && !old_enter; - old_enter = key[KEY_ENTER]; + const bool enter = key[SDLK_RETURN] && !old_enter; + old_enter = key[SDLK_RETURN]; if((enter) && message_entry.text().empty() == false) { config msg; @@ -156,7 +156,7 @@ RESULT enter(display& disp, config& game_data) message_entry.clear(); } - if(key[KEY_ESCAPE] || quit_game.process(mousex,mousey,left_button)){ + if(key[SDLK_ESCAPE] || quit_game.process(mousex,mousey,left_button)){ return QUIT; } diff --git a/src/multiplayer_lobby.hpp b/src/multiplayer_lobby.hpp index 042bddbed97..5e31d711778 100644 --- a/src/multiplayer_lobby.hpp +++ b/src/multiplayer_lobby.hpp @@ -4,10 +4,14 @@ #include "config.hpp" #include "display.hpp" +//this module controls the multiplayer lobby. A section on the server which +//allows players to chat, create games, and join games. namespace lobby { enum RESULT { QUIT, CREATE, JOIN }; +//function which controls the lobby, and will result in the player creating +//a game, joining a game, or quitting the lobby. RESULT enter(display& disp, config& data); } diff --git a/src/network.hpp b/src/network.hpp index 16db6ce7454..9765ea2f589 100644 --- a/src/network.hpp +++ b/src/network.hpp @@ -7,8 +7,12 @@ #include +//this module wraps the network interface. + namespace network { +//a network manager must be created before networking can be used. +//it must be destroyed only after all networking activity stops. struct manager { manager(); ~manager(); @@ -17,7 +21,11 @@ private: bool free_; }; +//a server manager causes listening on a given port to occur +//for the duration of its lifetime. struct server_manager { + //if create_server is false, then the object has no effect. + //throws error. server_manager(int port=15000, bool create_server=true); ~server_manager(); @@ -27,16 +35,43 @@ private: typedef TCPsocket connection; +//the number of peers we are connected to size_t nconnections(); + +//if we are currently accepting connections bool is_server(); +//function to attempt to connect to a remote host. Returns +//the new connection on success, or 0 on failure. +//throws error. connection connect(const std::string& host, int port=15000); + +//function to accept a connection from a remote host. If no +//host is attempting to connect, it will return 0 immediately. +//otherwise returns the new connection. +//throws error. connection accept_connection(); + +//function to disconnect from a certain host, or close all +//connections if connection_num is 0 void disconnect(connection connection_num=0); + +//function to queue a disconnection. Next time receive_data is +//called, it will generate an error on the given connection. +//(and presumably then the handling of the error will include +// closing the connection) void queue_disconnect(connection connection_num); -connection receive_data(config& cfg, connection connection_num=0, int tout=0); +//function to receive data from either a certain connection, or +//all connections if connection_num is 0. Will store the data +//received in cfg. Times out after timeout milliseconds. Returns +//the connection that data was received from, or 0 if timeout +//occurred. Throws error if an error occurred. +connection receive_data(config& cfg, connection connection_num=0, + int timeout=0); +//function to send data down a given connection, or broadcast +//to all peers if connection_num is 0. throws error. void send_data(const config& cfg, connection connection_num=0); struct error diff --git a/src/pathfind.hpp b/src/pathfind.hpp index 2ccb4bc2579..c96c7c8568d 100644 --- a/src/pathfind.hpp +++ b/src/pathfind.hpp @@ -25,38 +25,65 @@ #include #include +//this module contains various pathfinding functions and utilities. + +//function which, given a location, will place all adjacent locations in +//res. res must point to an array of 6 location objects. void get_adjacent_tiles(const gamemap::location& a, gamemap::location* res); + +//function which tells if two locations are adjacent. bool tiles_adjacent(const gamemap::location& a, const gamemap::location& b); +//function which gives the number of hexes between two tiles (i.e. the minimum +//number of hexes that have to be traversed to get from one hex to the other) size_t distance_between(const gamemap::location& a, const gamemap::location& b); +//function which will find a location on the board that is as near to loc as +//possible, but which is unoccupied by any units. If terrain is not 0, then +//the location found must be of the given terrain type, and must have a path +//of that terrain type to loc. +// +//if no valid location can be found, it will return a null location. gamemap::location find_vacant_tile(const gamemap& map, const std::map& un, const gamemap::location& loc, gamemap::TERRAIN terrain=0); +//function which determines if a given location is an enemy zone of control bool enemy_zoc(const gamemap& map,const std::map& units, const gamemap::location& loc,const team& current_team,int side); +//object which contains all the possible locations a unit can move to, with +//associated best routes to those locations. struct paths { paths() {} + + //construct a list of paths for the unit at loc. + //ignore_zocs: determines whether unit has to stop upon entering an ezoc + //allow_teleport: indicates whether unit teleports between villages + //additional_turns: if 0, paths for how far the unit can move this turn + //will be calculated. If 1, paths for how far the unit can move by the + //end of next turn will be calculated, and so forth. paths(const gamemap& map, const game_data& gamedata, const std::map& units, const gamemap::location& loc, std::vector& teams, bool ignore_zocs, bool allow_teleport, int additional_turns=0); + //structure which holds a single route between one location and another. struct route { route() : move_left(0) {} std::vector steps; - int move_left; + int move_left; //movement unit will have left at end of the route. }; typedef std::map routes_map; routes_map routes; }; +//function which, given a unit and a route the unit can move on, will +//return the number of turns it will take the unit to traverse the route. int route_turns_to_complete(const unit& u, const gamemap& map, const paths::route& rt); diff --git a/src/playturn.cpp b/src/playturn.cpp index e2b6eee4be9..89d7ec5b03f 100644 --- a/src/playturn.cpp +++ b/src/playturn.cpp @@ -147,16 +147,16 @@ void turn_info::turn_slice() const int mouse_flags = SDL_GetMouseState(&mousex,&mousey); tooltips::process(mousex,mousey,mouse_flags & SDL_BUTTON_LMASK); - if(key_[KEY_UP] || mousey == 0) + if(key_[SDLK_UP] || mousey == 0) gui_.scroll(0.0,-preferences::scroll_speed()); - if(key_[KEY_DOWN] || mousey == gui_.y()-1) + if(key_[SDLK_DOWN] || mousey == gui_.y()-1) gui_.scroll(0.0,preferences::scroll_speed()); - if(key_[KEY_LEFT] || mousex == 0) + if(key_[SDLK_LEFT] || mousex == 0) gui_.scroll(-preferences::scroll_speed(),0.0); - if(key_[KEY_RIGHT] || mousex == gui_.x()-1) + if(key_[SDLK_RIGHT] || mousex == gui_.x()-1) gui_.scroll(preferences::scroll_speed(),0.0); } diff --git a/src/show_dialog.cpp b/src/show_dialog.cpp index 490ae22d577..9a44165e357 100644 --- a/src/show_dialog.cpp +++ b/src/show_dialog.cpp @@ -468,11 +468,11 @@ int show_dialog(display& disp, SDL_Surface* image, const bool new_right_button = mouse_flags&SDL_BUTTON_RMASK; const bool new_left_button = mouse_flags&SDL_BUTTON_LMASK; - const bool new_key_down = key[KEY_SPACE] || key[KEY_ENTER] || - key[KEY_ESCAPE]; + const bool new_key_down = key[SDLK_SPACE] || key[SDLK_RETURN] || + key[SDLK_ESCAPE]; - const bool new_up_arrow = key[KEY_UP]; - const bool new_down_arrow = key[KEY_DOWN]; + const bool new_up_arrow = key[SDLK_UP]; + const bool new_down_arrow = key[SDLK_DOWN]; const bool new_page_up = key[SDLK_PAGEUP]; const bool new_page_down = key[SDLK_PAGEDOWN]; @@ -484,7 +484,7 @@ int show_dialog(display& disp, SDL_Surface* image, } - if(!key_down && key[KEY_ENTER] && + if(!key_down && key[SDLK_RETURN] && (type == YES_NO || type == OK_CANCEL)) { if(text_widget_text != NULL && use_textbox) @@ -497,11 +497,11 @@ int show_dialog(display& disp, SDL_Surface* image, } } - if(!key_down && key[KEY_ESCAPE] && type == MESSAGE) { + if(!key_down && key[SDLK_ESCAPE] && type == MESSAGE) { return -1; } - if(!key_down && key[KEY_ESCAPE] && + if(!key_down && key[SDLK_ESCAPE] && (type == YES_NO || type == OK_CANCEL)) { if(menu_.height() == 0) { @@ -663,7 +663,7 @@ TITLE_RESULT show_title(display& screen) CKey key; - bool last_escape = key[KEY_ESCAPE]; + bool last_escape = key[SDLK_ESCAPE]; update_whole_screen(); @@ -693,10 +693,10 @@ TITLE_RESULT show_title(display& screen) if(quit_button.process(mousex,mousey,left_button)) return QUIT_GAME; - if(!last_escape && key[KEY_ESCAPE]) + if(!last_escape && key[SDLK_ESCAPE]) return QUIT_GAME; - last_escape = key[KEY_ESCAPE]; + last_escape = key[SDLK_ESCAPE]; screen.video().flip();