/* Definitions for sides in Xconq. Copyright (C) 1987-1989, 1991-1997, 1999-2000 Stanley T. Shebs. Xconq is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. See the file COPYING. */ /* A side mask is a bit vector, where the bit position corresponds to the side number. */ #if MAXSIDES < 31 typedef int SideMask; #define NOSIDES (0) #define ALLSIDES (-1) #define add_side_to_set(side,mask) ((mask) | (1 << ((side) ? (side)->id : 0))) #define remove_side_from_set(side,mask) \ ((mask) & ~(1 << ((side) ? (side)->id : 0))) #define side_in_set(side,mask) ((mask) & (1 << ((side) ? (side)->id : 0))) #else not implemented yet #endif /* MAXSIDES */ /* Doctrine is policy info that units and players use to help decide behavior. */ typedef struct a_doctrine { short id; /* a unique id */ char *name; /* a distinguishing name for the doctrine */ short resupply_percent; /* do resupply task if below this */ short rearm_percent; /* do resupply of ammo if below this */ short repair_percent; /* do repairs if hp at or below this */ short *construction_run; /* number of each type to build usually */ short locked; /* true if values can't be changed */ struct a_doctrine *next; /* pointer to next doctrine defined */ } Doctrine; /* A standing order is a conditional order that applies to any matching unit not already doing a task. */ enum sordercond { sorder_always, sorder_at, sorder_in, sorder_near }; typedef struct a_standing_order { char *types; /* unit types to which order applies */ enum sordercond condtype; /* type of condition to trigger on */ int a1, a2, a3; /* parameters to test (x, y, etc) */ struct a_task *task; /* task to perform */ struct a_standing_order *next; /* link to next standing order for side */ } StandingOrder; /* Each Xconq player is a "side" - more or less one country. A side may or may not be played by a person, and may or may not have a display attached to it. Each side has a different view of the world. */ typedef struct a_side { int id; /* a unique id */ Obj *symbol; /* a symbol bound to side's id */ /* Name-related slots. */ char *name; /* proper name of this side */ char *longname; /* the long name of this side */ char *shortname; /* the long name of this side */ char *noun; /* the noun describing a member of this side */ char *pluralnoun; /* the noun describing several members */ char *adjective; /* adjective for members of this side */ char *colorscheme; /* names of the side's characteristic colors */ char *emblemname; /* name of the side's emblem */ char **unitnamers; /* array of unit naming method names */ Obj *featurenamers; /* list of feature naming methods */ short nameslocked; /* true if names may not be changed by player */ char *sideclass; /* general type or class description */ /* Relationships with other sides, types, etc. */ struct a_unit *self_unit; /* unit that embodies side */ short self_unit_id; /* id of unit that embodies side */ struct a_side *controlled_by; /* side controlling this one */ short controlled_by_id; /* id of controlling side */ SideMask knows_about; /* true if side knows about another side */ short *trusts; /* true if side trusts another side */ short *trades; short *startwith; /* how many units of each type at start of game */ short *counts; /* array of numbers for identifying units */ short *tech; /* tech level for each unit type */ short *inittech; /* tech level at beginning of turn */ short *action_priorities; /* action priority for each unit type */ short *already_seen; /* chance that other units already seen */ short *already_seen_indep; /* chance that independent units already seen */ Doctrine *default_doctrine; /* fallback doctrine */ Doctrine **udoctrine; /* array of per-unit-type doctrines */ short doctrines_locked; /* true if all doctrines locked */ StandingOrder *orders; /* list of standing orders for the side */ StandingOrder *last_order; char *uorders; /* bit vector of types that have orders */ Obj *possible_units; /* list of units to give to side */ short ai_may_resign; /* true if AI may draw or resign on its own */ short *advance; /* State of research (accum pts) for each */ /* advance. Set to -1 when completed. */ short research_topic; /* advance that the side is working on */ short autoresearch; /* TRUE if next research topic autoselected */ short *treasury; /* globally available supply of each material type */ short *c_rates; /* material conversion rates */ /* View layers. */ char *terrview; /* ptr to view of terrain */ char **auxterrview; /* ptr to view of aux terrain */ short *terrviewdate; /* ptr to dates of view of terrain */ short **auxterrviewdate; /* ptr to dates of view of aux terrain */ struct a_unit_view **unit_views; /* ptr to table of views of units */ short **materialview; /* ptr to view of cell materials */ short **materialviewdate; /* ptr to dates of view of cell materials */ short *tempview; /* ptr to view of temperature */ short *tempviewdate; /* ptr to dates of view of temperature */ short *cloudview; /* ptr to view of clouds */ short *cloudbottomview; /* ptr to view of cloud bottoms */ short *cloudheightview; /* ptr to view of cloud heights */ short *cloudviewdate; /* ptr to dates of view of clouds */ short *windview; /* ptr to view of winds */ short *windviewdate; /* ptr to dates of view of winds */ /* Progress and status within game. */ short ingame; /* true if side participating in game */ short everingame; /* true if side ever participated in a turn */ short priority; /* overall action priority of this side */ short status; /* -1/0/1 for lost/draw/won */ short *scores; /* array of scores managed by scorekeepers */ Obj *rawscores; /* score data as read from file */ short willingtodraw; /* will this side go along with quitters? */ short autofinish; /* turn done when all units acted */ short finishedturn; /* true when side wants to go to next turn */ short turntimeused; /* seconds used this turn */ short totaltimeused; /* total seconds used */ short timeouts; /* total timeouts used */ short timeoutsused; /* total timeouts used */ short curactor_pos; /* index in actionvector to current unit */ struct a_unit *curactor; short curactor_id; /* Setup. */ short advantage; /* actual advantage */ short minadvantage; /* min advantage requestable during init */ short maxadvantage; /* max of same */ short init_center_x, init_center_y; /* center of preferred initial view */ Obj *instructions; /* notes to player about the game */ /* Other. */ short last_notice_date; /* last turn during which notice was posted */ short realtimeout; /* how long to wait before just going ahead */ long startbeeptime; /* after this time, beep to signal next turn */ short *gaincounts; /* array of counts of unit gains by the side */ short *losscounts; /* array of counts of losses by the side */ long **atkstats; /* array of counts of attacks by units */ long **hitstats; /* array of damage done by unit attacks */ /* Pointers to the other major structures of a side. */ struct a_player *player; /* pointer to data about the player */ short playerid; /* numeric id of the player */ struct a_ui *ui; /* pointer to all the user interface data */ Obj *uidata; /* read/write form of user interface state */ short aitype; /* type of AI making decisions */ struct a_ai *ai; /* pointer to the AI making decisions */ Obj *aidata; /* readable/writable form of AI state */ struct a_rui *rui; /* pointer to interface data if remote */ struct a_rai *rai; /* pointer to AI data if remote */ /* Misc working slots, never saved. */ short startx, starty; /* approx center of side's "country" */ short busy; /* true when side state not saveable */ short finalradius; short willingtosave; /* will this side go along with saving game? */ /* True if the side sees everything. Right now this is just a cache for g_see_all(). Note in particular that becoming a designer should not change this value. */ short see_all; /* True if the side's interface should display everything. This is seeded from side->see_all, and also becomes true when designing or when the game is over. */ short show_all; /* True if the value of show_all can be changed by the player. This is normally off, but can be toggled while designing or after the game is over. */ short may_set_show_all; short unit_view_restored; /* true if unit view was read in */ #ifdef DESIGNERS short designer; /* true if side is doing scenario design */ #endif /* DESIGNERS */ /* Various caches, should be possible to recalc as needed. */ short *uavail; /* vector of types allowed on this side (as determined by u_possible_sides)*/ short *canbuild; /* vector of unit types that side has advances to build */ short *canresearch; /* vector of advances that side has advances to research */ struct a_unit *unithead; /* points to list of all units on this side */ struct a_unitvector *actionvector; /* vector of acting units */ short numwaiting; /* number of units waiting to get orders */ short *coverage; /* indicates how many looking at this cell */ short *alt_coverage; /* indicates minimum altitude visible */ short *numunits; /* number of units the side has */ short numacting; /* number of units that can do things */ short numfinished; /* number of units that have finished acting */ long turnstarttime; /* real time at start of turn */ long lasttime; /* when clock started counting down again */ long turnfinishtime; /* real time when we've finished interacting */ long laststarttime; /* ? */ int point_value_cache; int point_value_valid; int prefixarg; /* cache of UI prefixarg, for generic cmds */ /* Links. */ struct a_side *next; /* pointer to next in list */ } Side; /* Some convenient macros. */ #define side_in_play(side) (side->ingame) /* Iteration over all sides. */ /* This is the old for_all_sides which does not include indepside. */ #define for_all_real_sides(v) \ for (v = (sidelist ? sidelist->next : NULL); v != NULL; v = v->next) /* This is the new indepside-including version of for_all_sides. It has replaced for_all_side_plus_indep everywhere. */ #define for_all_sides(v) \ for (v = sidelist; v != NULL; v = v->next) /* Macros for accessing and setting a side's view data. In general, interfaces should go through these macros instead of accessing the world's state directly. */ #define terrain_view(s,x,y) \ ((s)->terrview ? aref((s)->terrview, x, y) : buildtview(terrain_at(x, y))) #define set_terrain_view(s,x,y,v) \ ((s)->terrview ? aset((s)->terrview, x, y, v) : 0) #define buildtview(t) ((t) + 1) #define vterrain(v) ((v) - 1) #define UNSEEN (0) #define terrain_view_date(s,x,y) \ ((s)->terrviewdate ? aref((s)->terrviewdate, x, y) : 0) #define set_terrain_view_date(s,x,y,v) \ ((s)->terrviewdate ? aset((s)->terrviewdate, x, y, v) : 0) #define aux_terrain_view(s,x,y,t) \ (((s)->auxterrview && (s)->auxterrview[t]) ? aref((s)->auxterrview[t], x, y) : (aux_terrain_defined(t) ? aux_terrain_at(x, y, t) : 0)) #define set_aux_terrain_view(s,x,y,t,v) \ (((s)->auxterrview && (s)->auxterrview[t]) ? aset((s)->auxterrview[t], x, y, v) : 0) #define aux_terrain_view_date(s,x,y,t) \ (((s)->auxterrviewdate && (s)->auxterrviewdate[t]) ? aref((s)->auxterrviewdate[t], x, y) : 0) #define set_aux_terrain_view_date(s,x,y,t,v) \ (((s)->auxterrviewdate && (s)->auxterrviewdate[t]) ? aset((s)->auxterrviewdate[t], x, y, v) : 0) /* Iterate over all unit views at a given location. Note that if side->see_all, the view objects are built on-the-fly and all actually point to the same bit of storage, so you can't expect to keep them from one loop iteration to the next. */ #define for_all_view_stack(s,x,y,uv) \ for ((uv) = unit_view_at(s,x,y); (uv) != NULL; (uv) = unit_view_next(s,x,y,uv)) /* Access to various properties of a unit view. */ #define view_type(uv) ((uv)->type) #define view_side(uv) (side_n((uv)->side_id)) #define view_size(uv) ((uv)->size) /* Get a pointer to the actual unit being viewed if possible. */ #define view_unit(uv) \ (((uv)->unit != NULL && (uv)->id == (uv)->unit->id) ? (uv)->unit : NULL) /* Manipulation of view of cell materials. */ #define material_view(s,x,y,m) \ (((s)->materialview && (s)->materialview[m]) ? aref((s)->materialview[m], x, y) : (cell_material_defined(m) ? material_at(x, y, m) : 0)) #define set_material_view(s,x,y,m,v) \ (((s)->materialview && (s)->materialview[m]) ? aset((s)->materialview[m], x, y, v) : 0) #define material_view_date(s,x,y,m) \ (((s)->materialviewdate && (s)->materialviewdate[m]) ? aref((s)->materialviewdate[m], x, y) : 0) #define set_material_view_date(s,x,y,m,v) \ (((s)->materialviewdate && (s)->materialviewdate[m]) ? aset((s)->materialviewdate[m], x, y, v) : 0) /* Manipulation of view of weather. */ #define temperature_view(s,x,y) \ ((s)->tempview ? aref((s)->tempview, x, y) : (temperatures_defined() ? temperature_at(x, y) : 0)) #define set_temperature_view(s,x,y,v) \ ((s)->tempview ? aset((s)->tempview, x, y, v) : 0) #define temperature_view_date(s,x,y) \ ((s)->tempviewdate ? aref((s)->tempviewdate, x, y) : 0) #define set_temperature_view_date(s,x,y,v) \ ((s)->tempviewdate ? aset((s)->tempviewdate, x, y, v) : 0) #define cloud_view(s,x,y) \ ((s)->cloudview ? aref((s)->cloudview, x, y) : (clouds_defined() ? raw_cloud_at(x, y) : 0)) #define set_cloud_view(s,x,y,v) \ ((s)->cloudview ? aset((s)->cloudview, x, y, v) : 0) #define cloud_view_date(s,x,y) \ ((s)->cloudviewdate ? aref((s)->cloudviewdate, x, y) : 0) #define set_cloud_view_date(s,x,y,v) \ ((s)->cloudviewdate ? aset((s)->cloudviewdate, x, y, v) : 0) #define cloud_bottom_view(s,x,y) \ ((s)->cloudbottomview ? aref((s)->cloudbottomview, x, y) : (cloud_bottoms_defined() ? raw_cloud_bottom_at(x, y) : 0)) #define set_cloud_bottom_view(s,x,y,v) \ ((s)->cloudbottomview ? aset((s)->cloudbottomview, x, y, v) : 0) #define cloud_bottom_view_date(s,x,y) \ ((s)->cloudbottomviewdate ? aref((s)->cloudbottomviewdate, x, y) : 0) #define set_cloud_bottom_view_date(s,x,y,v) \ ((s)->cloudbottomviewdate ? aset((s)->cloudbottomviewdate, x, y, v) : 0) #define cloud_height_view(s,x,y) \ ((s)->cloudheightview ? aref((s)->cloudheightview, x, y) : (cloud_heights_defined() ? raw_cloud_height_at(x, y) : 0)) #define set_cloud_height_view(s,x,y,v) \ ((s)->cloudheightview ? aset((s)->cloudheightview, x, y, v) : 0) #define cloud_height_view_date(s,x,y) \ ((s)->cloudheightviewdate ? aref((s)->cloudheightviewdate, x, y) : 0) #define set_cloud_height_view_date(s,x,y,v) \ ((s)->cloudheightviewdate ? aset((s)->cloudheightviewdate, x, y, v) : 0) #define wind_view(s,x,y) \ ((s)->windview ? aref((s)->windview, x, y) : (winds_defined() ? raw_wind_at(x, y) : CALM)) #define set_wind_view(s,x,y,v) \ ((s)->windview ? aset((s)->windview, x, y, v) : 0) #define wind_view_date(s,x,y) \ ((s)->windviewdate ? aref((s)->windviewdate, x, y) : 0) #define set_wind_view_date(s,x,y,v) \ ((s)->windviewdate ? aset((s)->windviewdate, x, y, v) : 0) /* Basic manipulation of vision coverage cache layer. */ #define cover(s,x,y) \ ((s)->coverage ? aref((s)->coverage, x, y) : 0) #define set_cover(s,x,y,v) \ ((s)->coverage ? aset((s)->coverage, x, y, v) : 0) #define add_cover(s,x,y,v) \ ((s)->coverage ? (aref((s)->coverage, x, y) += (v)) : 0) #define alt_cover(s,x,y) \ ((s)->alt_coverage ? aref((s)->alt_coverage, x, y) : 0) #define set_alt_cover(s,x,y,v) \ ((s)->alt_coverage ? aset((s)->alt_coverage, x, y, v) : 0) /* Tests both that s can have a treasury and that m can be stored in it. */ #define side_has_treasury(s,m) (s != indepside ? m_treasury(m) : g_indepside_has_treasury() ? m_treasury(m) : FALSE) /* Tests of who/what runs the side. */ #define side_wants_display(s) ((s)->player && (s)->player->displayname) #define side_wants_ai(s) ((s)->player && (s)->player->aitypename) #define side_has_display(s) (((s)->ui) != NULL || ((s)->rui) != NULL) #define side_has_local_display(s) ((s)->ui != NULL) #define side_has_ai(s) (((s)->ai) != NULL || ((s)->rai) != NULL) #define side_has_local_ai(s) ((s)->ai != NULL) /* Tests of side state. */ #define side_lost(s) ((s) != NULL && !(s)->ingame && (s)->status < 0) #define side_drew(s) ((s) != NULL && !(s)->ingame && (s)->status == 0) #define side_won(s) ((s) != NULL && !(s)->ingame && (s)->status > 0) #define side_gain_count(s,u,r) (((s)->gaincounts)[num_gain_reasons*(u)+(r)]) #define side_loss_count(s,u,r) (((s)->losscounts)[num_loss_reasons*(u)+(r)]) #define side_atkstats(s,a,d) ((s)->atkstats[a] ? ((s)->atkstats[a])[d] : 0) #define side_hitstats(s,a,d) ((s)->hitstats[a] ? ((s)->hitstats[a])[d] : 0) #define terrain_visible(side, x, y) \ ((side)->see_all || (terrain_view((side), wrapx(x), (y)) != UNSEEN)) #define borders_visible(side, x, y, d) \ ((side)->see_all || seen_border((side), (x), (y), (d))) #define units_visible(side, x, y) \ ((side)->see_all || (cover((side), wrapx(x), (y)) >= 1)) #define has_advance(side,a) ((side)->advance[(a)] == -1) #define side_can_build(side,a) ((side)->canbuild != NULL ? (side)->canbuild[(a)] : TRUE) #define side_can_research(side,a) ((side)->canresearch != NULL ? (side)->canresearch[(a)] : TRUE) #define inactive_indepside(side) \ ((side) == indepside && !side_has_ai(side) && !side_has_display(side)) #ifdef DESIGNERS #define is_designer(side) (side->designer) #else /* DESIGNERS */ #define is_designer(side) (FALSE) #endif /* DESIGNERS */ #define for_all_doctrines(d) \ for ((d) = doctrine_list; (d) != NULL; (d) = (d)->next) /* Side-related variables. */ extern Side *sidelist; extern Side *lastside; extern Side *indepside; extern Side *curside; extern Side *tmpside; extern int numsides; extern int numtotsides; extern int numplayers; #ifdef DESIGNERS extern int numdesigners; #endif /* DESIGNERS */ /* Definition of an agreement between sides. */ typedef struct a_agreement { short id; /* a unique id */ char *typename; /* a descriptive general name */ char *name; /* the specific name of this agreement */ int state; /* is this agreement in effect */ SideMask drafters; /* sides drafting the agreement */ SideMask proposers; /* sides ready to propose the draft agreement */ SideMask signers; /* proposed list of signers */ SideMask willing; /* sides that have indicated agreement so far */ SideMask knownto; /* sides that are aware of signed agreement */ struct a_obj *terms; /* list of specific terms */ short enforcement; /* true if program should try to enforce terms */ struct a_agreement *next; } Agreement; enum { draft, /* agreement is circulating among drafters */ proposed, /* agreement proposed to prospective signers */ in_force, /* agreement is active */ moribund /* agreement has expired */ }; /* Iteration over all agreements in the game. */ #define for_all_agreements(v) for (v = agreement_list; v != NULL; v = v->next) #define any_agreements() (agreement_list != NULL) #define side_signed_agreement(side,ag) ((ag)->signers[side_n(side)]) #define side_willing_agreement(side,ag) ((ag)->willing[side_n(side)]) #define side_knows_about_agreement(side,ag) ((ag)->knownto[side_n(side)]) /* Agreement-related variables. */ extern int num_agreements; extern Agreement *agreement_list; extern Agreement *last_agreement; /* Note: Can't use the "Unit" typedef below, must use "struct a_unit". */ extern void init_sides(void); extern Side *create_side(void); extern void init_side_unithead(Side *side); extern int side_has_units(Side *side); extern void init_doctrine(Side *side); extern void init_self_unit(Side *side); extern int init_view(Side *side); extern void calc_start_xy(Side *side); extern char *side_name(Side *side); extern char *side_adjective(Side *side); extern int side_number(Side *side); extern Side *side_n(int n); extern Side *find_side_by_name(char *str); extern int side_controls_side(Side *side, Side *side2); extern int side_controls_unit(Side *side, struct a_unit *unit); extern int side_sees_unit(Side *side, struct a_unit *unit); extern int side_sees_image(Side *side, struct a_unit *unit); extern int num_units_in_play(Side *side, int u); extern int num_units_incomplete(Side *side, int u); extern struct a_unit *find_next_unit(Side *side, struct a_unit *prevunit); extern struct a_unit *find_prev_unit(Side *side, struct a_unit *nextunit); extern struct a_unit *find_next_actor(Side *side, struct a_unit *prevunit); extern struct a_unit *find_prev_actor(Side *side, struct a_unit *nextunit); extern struct a_unit *find_next_mover(Side *side, struct a_unit *prevunit); extern struct a_unit *find_prev_mover(Side *side, struct a_unit *nextunit); extern struct a_unit *find_next_awake_mover(Side *side, struct a_unit *prevunit); extern struct a_unit *find_prev_awake_mover(Side *side, struct a_unit *nextunit); extern int side_initacp(Side *side); extern int side_acp(Side *side); extern int side_acp_reserved(Side *side); extern int using_tech_levels(void); extern void remove_side_from_game(Side *side); extern int num_displayed_sides(void); extern int trusted_side(Side *side1, Side *side2); extern int enemy_side(Side *s1, Side *s2); extern int allied_side(Side *s1, Side *s2); extern int neutral_side(Side *s1, Side *s2); extern void reveal_side(Side *sender, Side *recipient, int *types); extern void receive_message(Side *side, Side *sender, char *str); extern struct a_unit_view *unit_view_at(Side *side, int x, int y); extern struct a_unit_view *unit_view_next(Side *side, int x, int y, struct a_unit_view *uview); extern void all_see_occupy(struct a_unit *unit, int x, int y, int inopen); extern void all_see_leave(struct a_unit *unit, int x, int y, int inopen); extern void cover_area(Side *side, struct a_unit *unit, struct a_unit *oldtransport, int x0, int y0, int x1, int y1); extern void reset_coverage(void); extern void calc_coverage(Side *side); extern void reset_all_views(void); extern void reset_view(Side *side); extern void react_to_seen_unit(Side *side, struct a_unit *unit, int x, int y); extern void all_see_cell(int x, int y); extern int see_cell(Side *side, int x, int y); extern void see_exact(Side *side, int x, int y); extern int seen_border(Side *side, int x, int y, int dir); extern void maybe_track(struct a_unit *unit); extern void maybe_lose_track(struct a_unit *unit, int nx, int ny); extern char *side_desig(Side *side); extern Side *parse_side_spec(char *str); extern int actual_advantage(Side *side); extern Doctrine *new_doctrine(int id); extern Doctrine *find_doctrine(int id); extern Doctrine *find_doctrine_by_name(char *name); extern Doctrine *clone_doctrine(Doctrine *doctrine); extern void set_doctrine(Side *side, char *spec); extern StandingOrder *new_standing_order(void); extern void add_standing_order(Side *side, StandingOrder *sorder, int pos); extern int parse_standing_order(Side *side, char *cmdstr); extern char *parse_unit_types(Side *side, char *str, char *utypevec); extern char *parse_order_cond(Side *side, char *str, StandingOrder *sorder); extern char *get_next_arg(char *str, char *buf, char **rsltp); extern char *standing_order_desc(StandingOrder *sorder, char *buf); extern void init_agreements(void); extern Agreement *create_agreement(int id); extern Agreement *find_agreement(int id); extern char *agreement_desig(Agreement *ag); extern void fn_set_terrain_view(int x, int y, int val); extern void fn_set_aux_terrain_view(int x, int y, int val); extern void fn_set_terrain_view_date(int x, int y, int val); extern void fn_set_aux_terrain_view_date(int x, int y, int val); extern void fn_set_material_view(int x, int y, int val); extern void fn_set_material_view_date(int x, int y, int val); extern void fn_set_temp_view(int x, int y, int val); extern void fn_set_temp_view_date(int x, int y, int val); extern void fn_set_cloud_view(int x, int y, int val); extern void fn_set_cloud_bottom_view(int x, int y, int val); extern void fn_set_cloud_height_view(int x, int y, int val); extern void fn_set_cloud_view_date(int x, int y, int val); extern void fn_set_wind_view(int x, int y, int val); extern void fn_set_wind_view_date(int x, int y, int val); extern int load_side_config(Side *side); extern void update_side_display_all_sides(Side *side, int rightnow);