xconq-cvs Mailing List for Xconq
Brought to you by:
elijah_meeks,
matthewskala
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(11) |
Dec
(102) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(77) |
Feb
(120) |
Mar
(105) |
Apr
(83) |
May
(18) |
Jun
(126) |
Jul
(35) |
Aug
(14) |
Sep
(6) |
Oct
(1) |
Nov
|
Dec
|
2006 |
Jan
|
Feb
|
Mar
(20) |
Apr
(43) |
May
(101) |
Jun
(11) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2007 |
Jan
|
Feb
|
Mar
|
Apr
(10) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
Update of /cvsroot/xconq/xconq/kernel In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv18084/kernel Modified Files: Tag: BRANCH_MCAMPO_PATH conq.h move.c plan.c read.c side.c task.c ui.c unit.h world.h Added Files: Tag: BRANCH_MCAMPO_PATH fsa.hpp pathfind.cc stlastar.hpp Log Message: Add changelog (mcampo.README) for BRANCH_MCAMPO_PATH. Add files necessary for A* pathfinder. Modify kernel to accomodate pathfinder. Change capture and hit-unit behavior. Index: world.h =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/world.h,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -C2 -d -r1.4 -r1.4.2.1 *** world.h 14 Mar 2005 01:48:31 -0000 1.4 --- world.h 8 Apr 2007 19:34:01 -0000 1.4.2.1 *************** *** 1354,1355 **** --- 1354,1381 ---- int *xfp, int *yfp); extern int num_people_at(int x, int y); + + #ifdef BRANCH_MCAMPO + /* pathfind interface */ + typedef struct a_position { + int x, y; // position coordinates + // int t; // terrain type: cell or connection? (presently not used) + int u; // transport type + } Position; + + typedef struct a_path_node { + Position p; + struct a_path_node* next; + } PathNode; + + PathNode* path_find (Unit *unit, Unit *unit2, int x, int y, int dist); + #endif + + enum move_to_state { + eitherway, + leftthenright, + rightthenleft, + leftonly, + rightonly, + path_not_searched, + path_searched + }; Index: ui.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/ui.c,v retrieving revision 1.20 retrieving revision 1.20.2.1 diff -C2 -d -r1.20 -r1.20.2.1 *** ui.c 17 Sep 2005 15:43:43 -0000 1.20 --- ui.c 8 Apr 2007 19:34:01 -0000 1.20.2.1 *************** *** 3393,3397 **** beep the player for trying to move a non-mobile unit. */ ! if (impl_move_to(side, unit, x, y, 0)) { return TRUE; } else { --- 3393,3397 ---- beep the player for trying to move a non-mobile unit. */ ! if (impl_move_to(side, unit, other, x, y, 0)) { return TRUE; } else { *************** *** 3696,3700 **** int ! impl_move_to(Side *side, Unit *unit, int x, int y, int dist) { #ifdef DESIGNERS --- 3696,3700 ---- int ! impl_move_to(Side *side, Unit *unit, Unit *unit2, int x, int y, int dist) { #ifdef DESIGNERS *************** *** 3706,3709 **** --- 3706,3724 ---- } #endif /* DESIGNERS */ + + #ifdef BRANCH_MCAMPO + if (unit2) { + // if possible, occupy unit2 + if (can_occupy(unit, unit2) && sides_allow_entry(unit, unit2)) { + net_set_occupy_task(unit, unit2); + return TRUE; + } + // move unit2's location if possible, or close to it + int dist = !side_thinks_it_can_put_type_at(side, unit->type, + unit2->x, unit2->y); + net_set_move_to_task (unit, unit2->x, unit2->y, dist); + return TRUE; + } + #endif // BRANCH_MCAMPO /* Check that we can put the unit at the destination. */ if (!side_thinks_it_can_put_type_at(side, unit->type, x, y)) { --- NEW FILE: pathfind.cc --- /* Pathfinding Copyright (C) 2007 Massimo Campostrini 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. */ // The present file contains code from astar/findpath.cpp: /////////////////////////////////////////////////////////////////////////////// // STL A* Search implementation // (C)2001 Justin Heyes-Jones // // Finding a path on a simple grid maze // This shows how to do shortest path finding using A* /* A* Algorithm Implementation using STL is Copyright (C)2001-2005 Justin Heyes-Jones Permission is given by the author to freely redistribute and include this code in any program as long as this credit is given where due. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. Use at your own risk! */ /////////////////////////////////////////////////////////////////////////////// #include "stlastar.hpp" #include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; #include "conq.h" #include "kernel.h" #ifdef BRANCH_MCAMPO int total_entry_cost(int u1, int u3, int x1, int y1, int z1, int u2, int x2, int y2, int z2); // from move.c int path_nodes_allocated=0; int move_cost (const int u, const Position& o, const Position& n) { // "eat" const int uu = u, ou=o.u, ox=o.x, oy=o.y, nu=n.u, nx=n.x, ny=n.y; if (distance(ox, oy, nx, ny)>1) { printf(" (error) "); fflush(stdout); } if (nu==NONUTYPE) { return total_move_cost (uu, ou, ox, oy, 0, nx, ny, 0); } else { return total_entry_cost(uu, ou, ox, oy, 0, nu, nx, ny, 0); } } bool can_do (const int u, const int mp) { // "eat" const int uu = u, mpu = mp; return type_can_have_enough_mp(uu, mpu); } bool can_move (int u, const Position& o, const Position& n) { return can_do(u, move_cost(u, o, n)); } bool any_unfriendly_at (Unit *unit, int x, int y) { Unit *unit2; for_all_stack(x, y, unit2) { if (!unit_trusts_unit(unit, unit2)) return true; } return false; } bool allowed_cell (Unit *unit, int x, int y) { return type_can_occupy_cell(unit->type, x, y) && terrain_visible(unit->side, x, y) && !any_unfriendly_at(unit, x, y); } bool allowed_transport (Unit *unit, Unit *unit2) { return type_can_occupy(unit->type, unit2) && sides_allow_entry(unit, unit2); } // C++ iterators #define for_all_cell_terrain_types(v) \ for (int v = 0; v < numttypes; ++v) \ if (t_is_cell(v)) // Class definitions class PathElement { public: Position p; PathElement (); PathElement (const Position& p_); PathElement (PathElement const*const pp); double GoalCostEstimate (const PathElement& nodeGoal) const; bool IsGoal (const PathElement &nodeGoal) const; bool GetSuccessors (AStarSearch<PathElement>* astarsearch, PathElement *parent_node) const; double GetCost (const PathElement& successor) const; bool IsSameState (const PathElement &rhs) const; void PrintNodeInfo (const int i, PathElement const*const parent) const; double GoalDistanceEstimate (const PathElement& nodeGoal) const; }; PathElement::PathElement() { p.x = -1; p.y = -1; // p.t = NONTTYPE; p.u = NONUTYPE; } PathElement::PathElement (const Position& p_) { p = p_; } PathElement::PathElement (PathElement const*const pp) { if (pp) { p = pp->p; } else { p.x = -1; p.y = -1; // p.t = NONTTYPE; p.u = NONUTYPE; } } bool operator== (const PathElement& a, const PathElement& b) { if (a.p.x != b.p.x) return false; if (a.p.y != b.p.y) return false; if (a.p.u != b.p.u) return false; return true; } bool operator!= (const PathElement& a, const PathElement& b) { return !(a == b); } bool PathElement::IsSameState (const PathElement &rhs) const { return *this == rhs; } class PathGlobals { public: Unit *unit; // the traveller int u; // unit type of the traveller int dist; // the requested distance PathElement goal; // cached computations double min_mp; // min cell mp for u vector<double> terrain_cost; // added cost for each cell bool init (Unit *unit_, Unit *unit2, const int x, const int y, const int dist_); }; PathGlobals PGlobals; bool PathGlobals::init (Unit *unit_, Unit *unit2, const int x, const int y, const int dist_) { unit = unit_; dist = dist_; if (!unit || dist<0) return false; u = unit->type; if (unit2) { goal.p.x = unit2->x; goal.p.y = unit2->y; goal.p.u = unit2->type; } else { goal.p.x = x; goal.p.y = y; goal.p.u = NONUTYPE; } if (dist==0 && !unit2 && !allowed_cell(unit, goal.p.x, goal.p.y)) return false; if (dist==0 && unit2 && !allowed_transport(unit, unit2)) return false; // compute the min mp needed to enter a cell int min_e=9999, min_l=9999; for_all_cell_terrain_types(t) { min_e = min(min_e, ut_mp_to_enter(u,t)); min_l = min(min_l, ut_mp_to_leave(u,t)); } min_mp = min_e + min_l; // add a (fractional) terrain cost, // so for the same mp's we favor transports, // then terrains with good productivity and low accident rate terrain_cost.resize(numttypes,0); for_all_cell_terrain_types(t) { terrain_cost[t] = 0.01 + 0.001*max(0,100-min(ut_productivity(u,t),100)) + 0.001*max(0,ut_accident_hit(u,t)); } return true; } void PathElement::PrintNodeInfo (const int i, PathElement const*const parent) const { printf("%2d (x=%d, y=%d, u=%d", i, p.x, p.y, p.u); if (parent) { int mc = move_cost(PGlobals.u, parent->p, p); printf(", cost = %d+%g", mc, parent->GetCost(*this)-mc); } int gx=PGlobals.goal.p.x, gy=PGlobals.goal.p.y; printf(", dist = %d)\n", distance(p.x, p.y, gx, gy)); fflush(stdout); } // Here's the heuristic function that estimates the distance from a Node // to the Goal. double PathElement::GoalDistanceEstimate (const PathElement& nodeGoal) const { // "eat" const int ox=p.x, oy=p.y, nx=nodeGoal.p.x, ny=nodeGoal.p.y; return PGlobals.min_mp * distance(ox, oy, nx, ny); } bool PathElement::IsGoal (const PathElement &nodeGoal) const { return *this == nodeGoal; } // given this node, what does it cost to move to successor. double PathElement::GetCost (const PathElement &successor) const { double cost = move_cost(PGlobals.u, p, successor.p); if (successor.p.u==NONUTYPE) // add a fractional cost, so we favor transports, // then terrains with good productivity and low accident rate cost += PGlobals.terrain_cost[terrain_at(successor.p.x,successor.p.y)]; return cost; } // This generates the successors to the given Node. It uses a helper function // called AddSuccessor to give the successors to the AStar class. // The A* specific initialisation is done for each node internally, so here // you just set the state information that is specific to the application bool PathElement::GetSuccessors (AStarSearch<PathElement> *astarsearch, PathElement *parent_node) const { Unit *unit = PGlobals.unit; int u=unit->type, ox=p.x, oy=p.y; int gx=PGlobals.goal.p.x, gy=PGlobals.goal.p.y; bool error=false; PathElement parent(parent_node); PathElement NewNode; // push each possible move except allowing the search to go backwards int dir; for_all_directions(dir) { int nx, ny, mp; if (point_in_dir(ox, oy, dir, &nx, &ny)) { NewNode.p.x = nx; NewNode.p.y = ny; NewNode.p.u = NONUTYPE; if ((allowed_cell(unit, nx, ny) && can_move(u, p, NewNode.p) && !(NewNode==parent)) || distance(gx, gy, nx, ny) <= PGlobals.dist && PGlobals.dist>0) error = error || !astarsearch->AddSuccessor(NewNode); if (distance(gx, gy, nx, ny) <= PGlobals.dist && PGlobals.dist>0) // no need to check for transports continue; Unit *unit2, *occ; for_all_stack(nx, ny, unit2) { if (allowed_transport(unit, unit2)) { NewNode.p.u = unit2->type; if (can_move(u, p, NewNode.p) && !(NewNode==parent)) error = error || !astarsearch->AddSuccessor(NewNode); } // Also try occupants; we could use the recursive occupant test for_all_occupants(unit2, occ) { if (allowed_transport(unit, occ)) { NewNode.p.u = occ->type; if (can_move(u, p, NewNode.p) && !(NewNode==parent)) error = error || !astarsearch->AddSuccessor(NewNode); } } } } } return !error; } // external interface // find a path for unit to move within dist of (x,y), // or occupy unit2 (if unit2!=NULL && dist==0) // return a pointer to a list of positions PathNode* path_find (Unit *unit, Unit *unit2, int x, int y, int dist) { if (dist>2) // pathtinding is likely to be very inefficient... return 0; if (!PGlobals.init(unit, unit2, x, y, dist)) // invalid parameters return 0; PathElement start; start.p.x = unit->x; start.p.y = unit->y; start.p.u = unit->transport ? unit->transport->type : NONUTYPE; // Create an instance of the search class AStarSearch<PathElement> astarsearch; // Set Start and goal states astarsearch.SetStartAndGoalStates(start, PGlobals.goal); unsigned int SearchState; unsigned int SearchSteps = 0; do { SearchState = astarsearch.SearchStep(); SearchSteps++; } while (SearchState == AStarSearch<PathElement>::SEARCH_STATE_SEARCHING); if (SearchState != AStarSearch<PathElement>::SEARCH_STATE_SUCCEEDED) { if (SearchState == AStarSearch<PathElement>::SEARCH_STATE_FAILED) { Dprintf("A* search terminated. Did not find goal state\n"); } else { Dprintf("PATH_FIND error #1 in path_find\n"); } // Once you're done with the solution you can free the nodes up astarsearch.FreeSolutionNodes(); return 0; } // Search succeeded // Copy the solution up to the requested distance from the goal PathNode* path = (PathNode*) xmalloc(sizeof(PathNode)); path_nodes_allocated++; int gx=PGlobals.goal.p.x, gy=PGlobals.goal.p.y; int count=0; PathNode* current=path; PathElement* parent=0; PathElement* node = astarsearch.GetSolutionStart(); while (1) { if (distance(gx, gy, node->p.x, node->p.y) < dist) break; current->p = node->p; parent = node; node = astarsearch.GetSolutionNext(); if (!node) break; current->next = (PathNode*) xmalloc(sizeof(PathNode)); path_nodes_allocated++; current = current->next; current->next = 0; count++; }; // Once you're done with the solution you can free the nodes up astarsearch.FreeSolutionNodes(); Dprintf("A* search succeeded: sol. steps = %d, total steps = %d, " "alloc. nodes = %d\n", count, astarsearch.GetStepCount(), path_nodes_allocated); return path; } #endif // #ifdef BRANCH_MCAMPO /////////////////////////////////////////////////////////////////////////////// Index: side.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/side.c,v retrieving revision 1.24 retrieving revision 1.24.2.1 diff -C2 -d -r1.24 -r1.24.2.1 *** side.c 2 Jul 2005 21:55:21 -0000 1.24 --- side.c 8 Apr 2007 19:34:01 -0000 1.24.2.1 *************** *** 774,778 **** side_controls_side(Side *side, Side *side2) { ! return (side == side2 || side2->controlled_by == side); } --- 774,778 ---- side_controls_side(Side *side, Side *side2) { ! return (side == side2 || (side2 && side2->controlled_by == side)); } Index: move.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/move.c,v retrieving revision 1.8 retrieving revision 1.8.2.1 diff -C2 -d -r1.8 -r1.8.2.1 *** move.c 28 Jul 2005 03:28:27 -0000 1.8 --- move.c 8 Apr 2007 19:34:01 -0000 1.8.2.1 *************** *** 35,39 **** static int unit_traverse_blockable_by(Unit *unit, Unit *unit2); static int any_friendly_at(Unit *unit, int x, int y); ! static int total_entry_cost(int u1, int u3, int x1, int y1, int z1, int u2, int x2, int y2, int z2); static int number_member(int x, Obj *lis); static int wind_value(Unit *unit, int angle, int force, Obj *effect, int maxval); --- 35,40 ---- static int unit_traverse_blockable_by(Unit *unit, Unit *unit2); static int any_friendly_at(Unit *unit, int x, int y); ! // static ! int total_entry_cost(int u1, int u3, int x1, int y1, int z1, int u2, int x2, int y2, int z2); static int number_member(int x, Obj *lis); static int wind_value(Unit *unit, int angle, int force, Obj *effect, int maxval); Index: conq.h =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/conq.h,v retrieving revision 1.15 retrieving revision 1.15.2.1 diff -C2 -d -r1.15 -r1.15.2.1 *** conq.h 10 Jul 2005 13:28:37 -0000 1.15 --- conq.h 8 Apr 2007 19:34:01 -0000 1.15.2.1 *************** *** 16,19 **** --- 16,20 ---- */ + #define BRANCH_MCAMPO 1 /* Elements of bitmask controlling display updates. */ Index: unit.h =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/unit.h,v retrieving revision 1.10 retrieving revision 1.10.2.1 diff -C2 -d -r1.10 -r1.10.2.1 *** unit.h 25 Jun 2005 22:57:48 -0000 1.10 --- unit.h 8 Apr 2007 19:34:01 -0000 1.10.2.1 *************** *** 670,673 **** --- 670,676 ---- TaskType type; /*!< the kind of task we want to do */ int args[MAXTASKARGS]; /*!< arguments */ + #ifdef BRANCH_MCAMPO + void *argptr; /*!< pointer argument */ + #endif short execnum; /*!< how many times this has been done */ short retrynum; /*!< number of immed failures so far */ Index: plan.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/plan.c,v retrieving revision 1.16 retrieving revision 1.16.2.1 diff -C2 -d -r1.16 -r1.16.2.1 *** plan.c 6 Aug 2005 19:27:12 -0000 1.16 --- plan.c 8 Apr 2007 19:34:01 -0000 1.16.2.1 *************** *** 3365,3370 **** for_all_material_types(m) { ! if (((um_base_consumption(u, m) > 0) ! || (um_consumption_per_move(u, m) > 0)) && (unit->transport == NULL)) { if (unit->side) --- 3365,3374 ---- for_all_material_types(m) { ! if (((um_base_consumption(u, m) > 0 ! #ifdef BRANCH_MCAMPO ! // only watch "important" materials ! && um_hp_per_starve(u, m) > 0 ! #endif ! ) || (um_consumption_per_move(u, m) > 0)) && (unit->transport == NULL)) { if (unit->side) Index: task.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/task.c,v retrieving revision 1.14.2.2 retrieving revision 1.14.2.3 diff -C2 -d -r1.14.2.2 -r1.14.2.3 *** task.c 8 Apr 2007 18:37:06 -0000 1.14.2.2 --- task.c 8 Apr 2007 19:34:01 -0000 1.14.2.3 *************** *** 18,36 **** #include "aiunit2.h" /* This is the number of tasks to allocate initially. More will always be allocated as needed, so this should be a "reasonable" value. */ - #ifndef INITMAXTASKS #define INITMAXTASKS 100 #endif - enum choicestate { - eitherway, - leftthenright, - rightthenleft, - leftonly, - rightonly - }; - static int compare_directions(const void *a0, const void *a1); static int test_for_buildable(int x, int y); --- 18,36 ---- #include "aiunit2.h" + void set_task_pathinfo (Task *task, int pathinfo); + int task_pathinfo (Task *task); + void free_task_path (Task *task); + + #ifdef BRANCH_MCAMPO + static int manage_path (Unit *unit, Task *task); + extern int path_nodes_allocated; + #endif + /* This is the number of tasks to allocate initially. More will always be allocated as needed, so this should be a "reasonable" value. */ #ifndef INITMAXTASKS #define INITMAXTASKS 100 #endif static int compare_directions(const void *a0, const void *a1); static int test_for_buildable(int x, int y); *************** *** 138,141 **** --- 138,144 ---- task->args[i] = 0; task->next = NULL; + #ifdef BRANCH_MCAMPO + task->argptr = NULL; + #endif return task; } *************** *** 171,175 **** for_all_stack(x, y, unit) { if (in_play(unit) ! && !completed(unit) && unit->type == tmpbuildutype && unit->side == tmpbuilder->side) { --- 174,178 ---- for_all_stack(x, y, unit) { if (in_play(unit) ! && !fullsized(unit) && unit->type == tmpbuildutype && unit->side == tmpbuilder->side) { *************** *** 203,207 **** if (!in_play(buildee)) return TASK_FAILED; ! if (completed(buildee)) return TASK_IS_COMPLETE; uc = buildee->type; --- 206,210 ---- if (!in_play(buildee)) return TASK_FAILED; ! if (fullsized(buildee)) return TASK_IS_COMPLETE; uc = buildee->type; *************** *** 260,264 **** if (task->args[1] != 0) { occ = find_unit(task->args[1]); ! if (in_play(occ) && occ->type == u2 && !completed(occ)) return occ; } --- 263,267 ---- if (task->args[1] != 0) { occ = find_unit(task->args[1]); ! if (in_play(occ) && occ->type == u2 && !fullsized(occ)) return occ; } *************** *** 266,270 **** for_all_occupants(unit, occ) { if (in_play(occ) ! && !completed(occ) && occ->type == u2 && occ->side == unit->side) --- 269,273 ---- for_all_occupants(unit, occ) { if (in_play(occ) ! && !fullsized(occ) && occ->type == u2 && occ->side == unit->side) *************** *** 274,278 **** for_all_stack(x, y, occ) { if (in_play(occ) ! && !completed(occ) && occ->type == u2 && occ->side == unit->side) { --- 277,281 ---- for_all_stack(x, y, occ) { if (in_play(occ) ! && !fullsized(occ) && occ->type == u2 && occ->side == unit->side) { *************** *** 328,382 **** do_capture_task(Unit *unit, Task *task) { ! int u = NONUTYPE, tu = NONUTYPE; ! Side *side = NULL, *tside = NULL; ! int n = -1; ! Unit *target = NULL; ! UnitView *uvtarget = NULL; ! int capmethod = CAPTURE_METHOD_ANY; ! int tx = -1, ty = -1, dist = -1; ! int cancapture = FALSE, canattack = FALSE, canfire = FALSE; ! ! n = task->args[2]; ! // Get out, if we have exceeded number of capture attempts. ! if (task->execnum > n) ! return TASK_IS_COMPLETE; ! u = unit->type; ! side = unit->side; ! // NOTE: Looking up the actual unit is cheating. ! // We need the uview by ID, not the unit. ! target = find_unit(task->args[0]); ! if (!in_play(target)) ! return TASK_FAILED; ! uvtarget = find_unit_view(side, target); ! if (!uvtarget) ! return TASK_FAILED; ! capmethod = task->args[1]; ! tx = uvtarget->x; ty = uvtarget->y; ! tu = uvtarget->type; ! tside = side_n(uvtarget->siden); ! dist = distance(tx, ty, unit->x, unit->y); ! canattack = ((capmethod & CAPTURE_METHOD_ATTACK) ! && valid(check_attack_action(unit, unit, target, 100))); ! canfire = ((capmethod & HIT_METHOD_FIRE) ! && (dist <= (uu_zoc_range(u, tu) + 1)) ! && valid(check_fire_at_action(unit, unit, target, -1))); ! cancapture = ((capmethod & CAPTURE_METHOD_CAPTURE) ! && valid(check_capture_action(unit, unit, target))); ! if (cancapture) { ! prep_capture_action(unit, unit, target); ! return TASK_PREPPED_ACTION; ! } ! else if (canattack) { ! prep_attack_action(unit, unit, target, 100); ! return TASK_PREPPED_ACTION; ! } ! else if (canfire) { ! prep_fire_at_action(unit, unit, target, -1); ! return TASK_PREPPED_ACTION; ! } ! // TODO: Handle using transports or occs to perform capture. ! // TODO: Handle using detonations to perform capture. - #if (0) /* (should be able to say how hard to try) */ tx = task->args[0]; ty = task->args[1]; --- 331,338 ---- do_capture_task(Unit *unit, Task *task) { ! int u = unit->type, tx, ty, tu2, ts2, dist; ! Unit *unit2; ! Side *us = unit->side; /* (should be able to say how hard to try) */ tx = task->args[0]; ty = task->args[1]; *************** *** 423,428 **** return TASK_FAILED; } - #endif - return TASK_FAILED; } --- 379,382 ---- *************** *** 482,536 **** do_hit_unit_task(Unit *unit, Task *task) { ! int u = NONUTYPE, tu = NONUTYPE; ! Side *side = NULL, *tside = NULL; ! Unit *target = NULL; ! UnitView *uvtarget = NULL; ! int n = -1; ! int tx = -1, ty = -1, dist = -1; ! int hitmethod = HIT_METHOD_NONE; ! int canattack = FALSE, canfire = FALSE, candet = FALSE; ! n = task->args[2]; ! // Get out, if we have exceeded number of hit attempts. ! if (task->execnum > n) return TASK_IS_COMPLETE; ! u = unit->type; ! side = unit->side; ! // NOTE: Looking up the actual unit is cheating. ! // We need the uview by ID, not the unit. ! target = find_unit(task->args[0]); ! if (!in_play(target)) ! return TASK_FAILED; ! uvtarget = find_unit_view(side, target); ! if (!uvtarget) ! return TASK_FAILED; ! hitmethod = task->args[1]; ! tx = uvtarget->x; ! ty = uvtarget->y; ! tu = uvtarget->type; ! tside = side_n(uvtarget->siden); dist = distance(tx, ty, unit->x, unit->y); - canattack = ((hitmethod & HIT_METHOD_ATTACK) - && valid(check_attack_action(unit, unit, target, 100))); - canfire = ((hitmethod & HIT_METHOD_FIRE) - && valid(check_fire_at_action(unit, unit, target, -1))); - candet = ((hitmethod & HIT_METHOD_DETONATE) - && valid(can_detonate(unit, unit)) - && (dist >= uu_detonation_range(u, tu))); - if (canattack) { - prep_attack_action(unit, unit, target, 100); - return TASK_PREPPED_ACTION; - } - else if (canfire) { - prep_fire_at_action(unit, unit, target, -1); - return TASK_PREPPED_ACTION; - } - else if (candet) { - prep_detonate_action(unit, unit, tx, ty, unit->z); - return TASK_PREPPED_ACTION; - } - // TODO: Handle using transports or occs to perform hit. - - #if (0) if (dist <= 1) { if (can_attack_any(unit, unit)) { --- 436,458 ---- do_hit_unit_task(Unit *unit, Task *task) { ! int u = unit->type, tx, ty, dist, movedist, tu, ts; ! Unit *unit2; ! UnitView *uview; ! Side *us = unit->side; ! /* Temporary hack. Ask the planner to re-evaluate continuation of ! this task. If it wants to, then it will issue a new one. If not, ! then move on and do something more productive. */ ! /* A better solution would be to add a new arg to the task that would ! tell it the number of times to attempt execution before returning to ! the planner for guidance. */ ! if (task->execnum > 3) return TASK_IS_COMPLETE; ! /* This is to hit a (given type/side of) unit at a given place. */ ! tx = task->args[0]; ! ty = task->args[1]; ! tu = task->args[2]; ! ts = task->args[3]; dist = distance(tx, ty, unit->x, unit->y); if (dist <= 1) { if (can_attack_any(unit, unit)) { *************** *** 570,574 **** } if (dist < u_range_min(u)) { ! // TODO: Retreat from target, and then fire. return TASK_FAILED; } --- 492,496 ---- } if (dist < u_range_min(u)) { ! /* should move further away */ return TASK_FAILED; } *************** *** 578,583 **** if (ts == uview->siden && tu == uview->type) { unit2 = view_unit(uview); ! if (unit2 ! && valid(check_fire_at_action(unit, unit, unit2, -1))) { prep_fire_at_action(unit, unit, unit2, -1); return TASK_PREPPED_ACTION; --- 500,504 ---- if (ts == uview->siden && tu == uview->type) { unit2 = view_unit(uview); ! if (unit2 && valid(check_fire_at_action(unit, unit, unit2, -1))) { prep_fire_at_action(unit, unit, unit2, -1); return TASK_PREPPED_ACTION; *************** *** 605,609 **** return TASK_IS_INCOMPLETE; } - #endif return TASK_FAILED; } --- 526,529 ---- *************** *** 747,750 **** --- 667,860 ---- } + int + allowed_transport_check (Unit *unit, Unit *unit2, int check) + { + if (!can_occupy(unit, unit2)) return 0; + if (!sides_allow_entry(unit, unit2)) return 0; + if (check && !valid(check_enter_action(unit, unit, unit2))) return 0; + return 1; + } + + /* Find a transport at x, y of type tt for unit */ + /* if tt==-2, find a transport of any type */ + /* if check is true, actually check the action */ + static Unit* + find_transport_at (Unit * unit, int x, int y, int tt, int check) + { + Unit *unit2, *occ; + if (tt==NONUTYPE) return NULL; + + for_all_stack(x, y, unit2) { + if ((tt==-2 || tt==unit2->type) && + allowed_transport_check(unit, unit2, check)) + return unit2; + + /* Perhaps an occupant... */ + /* (We could use the recursive occupant test, but if + things are that complicated, the player should probably + exercise manual control here.) */ + for_all_occupants(unit2, occ) { + if ((tt==-2 || tt==occ->type) + && allowed_transport_check(unit, occ, check)) + return occ; + } + } + + return NULL; + } + + static TaskOutcome + do_single_move_subtask (Unit *unit, Task *task, + Unit *transport, int tt, + int tx, int ty, int tdist) + { + int dist = distance(tx, ty, unit->x, unit->y), check; + Unit *unit2 = (tt==NONUTYPE || tt==-2) ? NULL : + find_transport_at(unit, tx, ty, tt, 1); + + if (transport && !in_play(transport)) { + return TASK_FAILED; + } + + if (dist<=tdist && (tdist>0 || unit->transport==transport)) { + /* We're there already, nothing more to do. */ + free_task_path(task); + return TASK_IS_COMPLETE; + } else if (dist<=1 && transport) { + if (valid(check_enter_action(unit, unit, transport))) { + prep_enter_action(unit, unit, transport); + return TASK_PREPPED_ACTION; + } else { + /* Try a couple times, then fail if not working. */ + return (task->execnum < 3 ? TASK_IS_INCOMPLETE : TASK_FAILED); + } + } else if (unit2 && valid(check_enter_action(unit, unit, unit2))) { + /* There's somebody that we can enter, so we prefer to do that. */ + prep_enter_action(unit, unit, unit2); + return TASK_PREPPED_ACTION; + } else { + /* Try a basic move action. */ + if (valid(check = check_move_action(unit, unit, tx, ty, unit->z))) { + /* Move into an empty cell. */ + prep_move_action(unit, unit, tx, ty, unit->z); + return TASK_PREPPED_ACTION; + } else { + /* If we're just short on mp, wait until the next turn to + try to move. */ + if (check == A_MOVE_NO_MP) { + notify(unit->side, + "%s is resting until next turn.", + unit_handle(unit->side, unit)); + set_unit_reserve(unit->side, unit, TRUE, FALSE); + return TASK_IS_INCOMPLETE; + } + Dprintf("%s move action fails check, result is %s\n", + unit_desig(unit), hevtdefns[check].name); + } + } + free_task_path(task); + return TASK_FAILED; + } + + void set_task_pathinfo (Task *task, int pathinfo) + { + if (task->type==TASK_MOVE_TO) { + task->args[4] = pathinfo; + } else if (task->type==TASK_OCCUPY) { + task->args[1] = pathinfo; + } + } + + int task_pathinfo (Task *task) + { + if (task->type==TASK_MOVE_TO) return task->args[4]; + if (task->type==TASK_OCCUPY ) return task->args[1]; + return eitherway; + } + + int task_dist (Task *task) + { + if (task->type==TASK_MOVE_TO) return task->args[3]; + return 0; + } + + void free_task_path (Task *task) + { + #ifdef BRANCH_MCAMPO + int count = 0; + if (task->argptr != NULL) { + PathNode* current; + for (current = (PathNode*) task->argptr; current; + current = current->next) { + free(current); + path_nodes_allocated--; + count++; + } + task->argptr = NULL; + set_task_pathinfo(task, path_not_searched); + } + #endif + } + + #ifdef BRANCH_MCAMPO + // path_find interface for the task + static int manage_path (Unit *unit, Task *task) + { + int tx, ty, dist; + Unit *unit2; + + if (task->type==TASK_MOVE_TO) { + tx = task->args[0]; + ty = task->args[1]; + dist = task->args[3]; + /* If there's somebody that we can enter, prefer to do that. */ + unit2 = find_transport_at(unit, tx, ty, -2, 0); + } else if (task->type==TASK_OCCUPY) { + unit2 = find_unit_dead_or_alive(task->args[0]); + if (!unit2 || !in_play(unit2)) { + set_task_pathinfo(task, eitherway); + return 0; + } + tx = unit2->x; + ty = unit2->y; + dist = 0; + } else { + set_task_pathinfo(task, eitherway); + return 0; + } + + // check that we are on the path + if (task->argptr) { + PathNode *pos = (PathNode*) task->argptr; + if (pos->p.x!=unit->x || pos->p.y!=unit->y) { + // we strayed from the path, try to find the path again + Dprintf("manage_path: %s is at %d,%d while the path is at " + "%d,%d: find a new path to %d,%d\n", + unit_handle(NULL, unit), unit->x, unit->y, + pos->p.x, pos->p.x, tx, ty); + free_task_path(task); + } + } + + // if we did not search for a path + if (task_pathinfo(task)==path_not_searched) { + if (task->argptr) { + Dprintf("PATH_FIND error #2 in manage_path\n"); + free_task_path(task); + } + set_task_pathinfo(task, path_searched); + // search for an optimized path to tx, ty + task->argptr = + (void *) path_find(unit, unit2, tx, ty, dist); + // if path_find failed, fall back to old way of moving + if (!task->argptr) { + set_task_pathinfo(task, eitherway); + } + } + + return 1; + } + #endif // BRANCH_MCAMPO + /* The move-to task is the main way for units to get from point A to point B. In addition to the destination, the task has a required *************** *** 828,887 **** case 0: /* We're there already, nothing more to do. */ ! return TASK_IS_COMPLETE; case 1: ! /* Adjacent cell, do a single move. */ ! /* But first, if there are units here already, prefer to ! interact with them. */ ! for_all_stack(tx, ty, unit2) { ! /* If there's somebody that we can enter, prefer to do that. */ ! if (can_occupy(unit, unit2) ! && valid(check_enter_action(unit, unit, unit2))) { ! prep_enter_action(unit, unit, unit2); ! return TASK_PREPPED_ACTION; ! } ! /* Perhaps an occupant... */ ! /* (We could use the recursive occupant test, but if ! things are that complicated, the player should probably ! exercise manual control here.) */ ! for_all_occupants(unit2, occ) { ! if (can_occupy(unit, occ) ! && valid(check_enter_action(unit, unit, occ))) { ! prep_enter_action(unit, unit, occ); ! return TASK_PREPPED_ACTION; ! } ! } ! } ! #if 0 /* auto-attack on move should be player-controlled... */ ! if (!trusted_side(unit->side, unit2->side)) { ! /* This is probably not a good idea, combat odds not ! taken into account. */ ! if (valid(check_attack_action(unit, unit, unit2, 100))) { ! prep_attack_action(unit, unit, unit2, 100); ! return TASK_PREPPED_ACTION; ! } else { ! continue; ! } ! } ! #endif ! /* Now try a basic move action. */ ! if (valid(check = check_move_action(unit, unit, tx, ty, unit->z))) { ! /* Moving into an empty cell. */ ! prep_move_action(unit, unit, tx, ty, unit->z); ! return TASK_PREPPED_ACTION; ! } else { ! /* If we're just short on mp, wait until the next turn to ! try to move. */ ! if (check == A_MOVE_NO_MP) { ! notify(unit->side, ! "%s is resting until next turn.", ! unit_handle(unit->side, unit)); ! set_unit_reserve(unit->side, unit, TRUE, FALSE); ! return TASK_IS_INCOMPLETE; ! } ! Dprintf("%s move action fails check, result is %s\n", ! unit_desig(unit), hevtdefns[check].name); ! return TASK_FAILED; ! } break; default: if (dist <= u_move_range(unit->type) --- 938,950 ---- case 0: /* We're there already, nothing more to do. */ ! free_task_path(task); ! return TASK_IS_COMPLETE; ! case 1: ! /* Do a single move, old or new style */ ! return do_single_move_subtask(unit, task, NULL, ! -2, tx, ty, task->args[3]); break; + default: if (dist <= u_move_range(unit->type) *************** *** 908,914 **** Unit *unit2; - #if (0) /* If on mobile transport, let it handle things. */ - /* Comment: Umm, no. What if unit is trying to get off mobile transport? */ if (unit->transport != NULL && mobile(unit->transport->type) --- 971,975 ---- *************** *** 918,922 **** --- 979,1009 ---- return TASK_IS_INCOMPLETE; } + + #ifdef BRANCH_MCAMPO + manage_path(unit, task); + + // if we have path information, use it + if (task->argptr) { + // default: move to destination + int nx = tx, ny = ty, nt = NONUTYPE, nd = task_dist(task); + + // remove the first node of the path + PathNode* pos = ((PathNode*) task->argptr)->next; + free(task->argptr); + path_nodes_allocated--; + task->argptr = (void*) pos; + // use the new first node, if available + if (pos) { + nx = pos->p.x; + ny = pos->p.y; + nt = pos->p.u; + nd = 0; + } + /* Do a single move to a (hopefully) adjacent cell . */ + return do_single_move_subtask(unit, task, NULL, nt, nx, ny, nd); + } #endif + // no path information, use the "old" code + numdirs = choose_move_dirs(unit, tx, ty, TRUE, plausible_move_dir, *************** *** 1114,1117 **** --- 1201,1205 ---- tx = transport->x; ty = transport->y; + /* (should also fail if we don't know where transport is anymore) */ if (unit->transport == transport) { *************** *** 2059,2073 **** Unit *transport = NULL; ! if (task->next) ! nexttask = task->next; ! /* If we were waiting for a transport, and are now in it, ! then don't wait. */ ! if ((nexttask != NULL) && (nexttask->type == TASK_OCCUPY)) { ! transport = find_unit_dead_or_alive(nexttask->args[0]); ! if (in_play(transport) && (transport == unit->transport)) { ! task->next = nexttask->next; ! free_task(nexttask); } - return TASK_IS_COMPLETE; } if (task->args[0] > 0) { --- 2147,2162 ---- Unit *transport = NULL; ! if (task->next) { ! nexttask = task->next; ! /* If we were waiting for a transport, and are now in it, ! then don't wait. */ ! if (nexttask->type == TASK_OCCUPY) { ! transport = find_unit_dead_or_alive(nexttask->args[0]); ! if (in_play(transport) && (transport == unit->transport)) { ! task->next = nexttask->next; ! free_task(nexttask); ! } ! return TASK_IS_COMPLETE; } } if (task->args[0] > 0) { *************** *** 2467,2470 **** --- 2556,2560 ---- free_task(Task *task) { + free_task_path(task); task->next = freetasks; freetasks = task; *************** *** 2550,2573 **** Task * ! create_capture_task(Unit *unit, int id, int capmethod, int n) { Task *task = create_task(TASK_CAPTURE); ! task->args[0] = id; ! task->args[1] = capmethod; ! task->args[2] = n; return task; } void ! set_capture_task(Unit *unit, int id, int capmethod, int n) { ! add_task(unit, CLEAR_AGENDA, create_capture_task(unit, id, capmethod, n)); } void ! push_capture_task(Unit *unit, int id, int capmethod, int n) { ! add_task(unit, 0, create_capture_task(unit, id, capmethod, n)); } --- 2640,2663 ---- Task * ! create_capture_task(Unit *unit, int x, int y, int u, int s) { Task *task = create_task(TASK_CAPTURE); ! task->args[0] = x; task->args[1] = y; ! task->args[2] = u; ! task->args[3] = s; return task; } void ! set_capture_task(Unit *unit, int x, int y, int u, int s) { ! add_task(unit, CLEAR_AGENDA, create_capture_task(unit, x, y, u, s)); } void ! push_capture_task(Unit *unit, int x, int y, int u, int s) { ! add_task(unit, 0, create_capture_task(unit, x, y, u, s)); } *************** *** 2601,2624 **** Task * ! create_hit_unit_task(Unit *unit, int id, int hitmethod, int n) { Task *task = create_task(TASK_HIT_UNIT); ! task->args[0] = id; ! task->args[1] = hitmethod; ! task->args[2] = n; return task; } void ! set_hit_unit_task(Unit *unit, int id, int hitmethod, int n) { ! add_task(unit, CLEAR_AGENDA, create_hit_unit_task(unit, id, hitmethod, n)); } void ! push_hit_unit_task(Unit *unit, int id, int hitmethod, int n) { ! add_task(unit, 0, create_hit_unit_task(unit, id, hitmethod, n)); } --- 2691,2714 ---- Task * ! create_hit_unit_task(Unit *unit, int x, int y, int u, int s) { Task *task = create_task(TASK_HIT_UNIT); ! task->args[0] = x; task->args[1] = y; ! task->args[2] = u; ! task->args[3] = s; return task; } void ! set_hit_unit_task(Unit *unit, int x, int y, int u, int s) { ! add_task(unit, CLEAR_AGENDA, create_hit_unit_task(unit, x, y, u, s)); } void ! push_hit_unit_task(Unit *unit, int x, int y, int u, int s) { ! add_task(unit, 0, create_hit_unit_task(unit, x, y, u, s)); } *************** *** 2643,2652 **** } - void - push_move_dir_task(Unit *unit, int dir, int n) - { - add_task(unit, 0, create_move_dir_task(unit, dir, n)); - } - Task * create_move_to_task(Unit *unit, int x, int y, int dist) --- 2733,2736 ---- *************** *** 2664,2667 **** --- 2748,2755 ---- task->args[3] = dist; task->args[4] = eitherway; + #ifdef BRANCH_MCAMPO + task->args[4] = path_not_searched; + #endif + return task; } *************** *** 2686,2689 **** --- 2774,2780 ---- task->args[0] = transport->id; task->args[1] = eitherway; + #ifdef BRANCH_MCAMPO + task->args[1] = path_not_searched; + #endif /* add a waiting period also? */ return task; --- NEW FILE: fsa.hpp --- /* A* Algorithm Implementation using STL is Copyright (C)2001-2005 Justin Heyes-Jones Permission is given by the author to freely redistribute and include this code in any program as long as this credit is given where due. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. Use at your own risk! FixedSizeAllocator class Copyright 2001 Justin Heyes-Jones This class is a constant time O(1) memory manager for objects of a specified type. The type is specified using a template class. Memory is allocated from a fixed size buffer which you can specify in the class constructor or use the default. Using GetFirst and GetNext it is possible to iterate through the elements one by one, and this would be the most common use for the class. I would suggest using this class when you want O(1) add and delete and you don't do much searching, which would be O(n). Structures such as binary trees can be used instead to get O(logn) access time. */ #ifndef FSA_H #define FSA_H #include <string.h> #include <stdio.h> template <class USER_TYPE> class FixedSizeAllocator { public: // Constants enum { FSA_DEFAULT_SIZE = 100 }; // This class enables us to transparently manage the extra data // needed to enable the user class to form part of the double-linked // list class struct FSA_ELEMENT { USER_TYPE UserType; FSA_ELEMENT *pPrev; FSA_ELEMENT *pNext; }; public: // methods FixedSizeAllocator( unsigned int MaxElements = FSA_DEFAULT_SIZE ) : m_MaxElements( MaxElements ), m_pFirstUsed( NULL ) { // Allocate enough memory for the maximum number of elements char *pMem = new char[ m_MaxElements * sizeof (FSA_ELEMENT) ]; m_pMemory = (FSA_ELEMENT *) pMem; // Set the free list first pointer m_pFirstFree = m_pMemory; // Clear the memory memset( m_pMemory, 0, sizeof( FSA_ELEMENT ) * m_MaxElements ); // Point at first element FSA_ELEMENT *pElement = m_pFirstFree; // Set the double linked free list for( unsigned int i=0; i<m_MaxElements; i++ ) { pElement->pPrev = pElement-1; pElement->pNext = pElement+1; pElement++; } // first element should have a null prev m_pFirstFree->pPrev = NULL; // last element should have a null next (pElement-1)->pNext = NULL; } ~FixedSizeAllocator() { // Free up the memory delete [] m_pMemory; } // Allocate a new USER_TYPE and return a pointer to it USER_TYPE *alloc() { FSA_ELEMENT *pNewNode = NULL; if( !m_pFirstFree ) { return NULL; } else { pNewNode = m_pFirstFree; m_pFirstFree = pNewNode->pNext; // if the new node points to another free node then // change that nodes prev free pointer... if( pNewNode->pNext ) { pNewNode->pNext->pPrev = NULL; } // node is now on the used list pNewNode->pPrev = NULL; // the allocated node is always first in the list if( m_pFirstUsed == NULL ) { pNewNode->pNext = NULL; // no other nodes } else { m_pFirstUsed->pPrev = pNewNode; // insert this at the head of the used list pNewNode->pNext = m_pFirstUsed; } m_pFirstUsed = pNewNode; } return reinterpret_cast<USER_TYPE*>(pNewNode); } // Free the given user type // For efficiency I don't check whether the user_data is a valid // pointer that was allocated. I may add some debug only checking // (To add the debug check you'd need to make sure the pointer is in // the m_pMemory area and is pointing at the start of a node) void free( USER_TYPE *user_data ) { FSA_ELEMENT *pNode = reinterpret_cast<FSA_ELEMENT*>(user_data); // manage used list, remove this node from it if( pNode->pPrev ) { pNode->pPrev->pNext = pNode->pNext; } else { // this handles the case that we delete the first node in the used list m_pFirstUsed = pNode->pNext; } if( pNode->pNext ) { pNode->pNext->pPrev = pNode->pPrev; } // add to free list if( m_pFirstFree == NULL ) { // free list was empty m_pFirstFree = pNode; pNode->pPrev = NULL; pNode->pNext = NULL; } else { // Add this node at the start of the free list m_pFirstFree->pPrev = pNode; pNode->pNext = m_pFirstFree; m_pFirstFree = pNode; } } // For debugging this displays both lists (using the prev/next list pointers) void Debug() { printf( "free list " ); FSA_ELEMENT *p = m_pFirstFree; while( p ) { printf( "%x!%x ", p->pPrev, p->pNext ); p = p->pNext; } printf( "\n" ); printf( "used list " ); p = m_pFirstUsed; while( p ) { printf( "%x!%x ", p->pPrev, p->pNext ); p = p->pNext; } printf( "\n" ); } // Iterators USER_TYPE *GetFirst() { return reinterpret_cast<USER_TYPE *>(m_pFirstUsed); } USER_TYPE *GetNext( USER_TYPE *node ) { return reinterpret_cast<USER_TYPE *> ( (reinterpret_cast<FSA_ELEMENT *>(node))->pNext ); } public: // data private: // methods private: // data FSA_ELEMENT *m_pFirstFree; FSA_ELEMENT *m_pFirstUsed; unsigned int m_MaxElements; FSA_ELEMENT *m_pMemory; }; #endif // defined FSA_H Index: read.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/read.c,v retrieving revision 1.12 retrieving revision 1.12.2.1 diff -C2 -d -r1.12 -r1.12.2.1 *** read.c 17 Jun 2005 02:54:11 -0000 1.12 --- read.c 8 Apr 2007 19:34:01 -0000 1.12.2.1 *************** *** 14,17 **** --- 14,20 ---- #include "imf.h" + void set_task_pathinfo (Task *task, int pathinfo); + int task_pathinfo (Task *task); + extern int actually_read_lisp; *************** *** 3991,3994 **** --- 3994,4009 ---- if (form != lispnil) read_warning("Excess args for task %s", task_desig(task)); + + #ifdef BRANCH_MCAMPO + // paths are not saved; force recomputation + if (task_pathinfo(task)==path_searched) + set_task_pathinfo(task, path_not_searched); + #else + // paths are not implemented in this version + if (task_pathinfo(task)==path_searched || + task_pathinfo(task)==path_not_searched) + set_task_pathinfo(task, eitherway); + #endif + return task; } --- NEW FILE: stlastar.hpp --- /* A* Algorithm Implementation using STL is Copyright (C)2001-2005 Justin Heyes-Jones Permission is given by the author to freely redistribute and include this code in any program as long as this credit is given where due. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. Use at your own risk! */ // used for text debugging #include <iostream> #include <stdio.h> //#include <conio.h> #include <assert.h> // stl includes #include <algorithm> #include <set> #include <vector> using namespace std; // fast fixed size memory allocator, used for fast node memory management #include "fsa.hpp" // Fixed size memory allocator can be disabled to compare performance // Uses std new and delete instead if you turn it off #define USE_FSA_MEMORY 1 // disable warning that debugging information has lines that are truncated // occurs in stl headers #pragma warning( disable : 4786 ) // The AStar search class. UserState is the users state space type template <class UserState> class AStarSearch { public: // data enum { SEARCH_STATE_NOT_INITIALISED, SEARCH_STATE_SEARCHING, SEARCH_STATE_SUCCEEDED, SEARCH_STATE_FAILED, SEARCH_STATE_OUT_OF_MEMORY, SEARCH_STATE_INVALID }; // A node represents a possible state in the search // The user provided state type is included inside this type public: class Node { public: Node *parent; // used during the search to record the parent of successor nodes Node *child; // used after the search for the application to view the search in reverse double g; // cost of this node + it's predecessors double h; // heuristic estimate of distance to goal double f; // sum of cumulative cost of predecessors and self and heuristic Node() : parent( 0 ), child( 0 ), g( 0.0f ), h( 0.0f ), f( 0.0f ) { } UserState m_UserState; }; // For sorting the heap the STL needs compare function that lets us compare // the f value of two nodes class HeapCompare_f { public: bool operator() ( const Node *x, const Node *y ) const { return x->f > y->f; } }; public: // methods // constructor just initialises private data AStarSearch( int MaxNodes = 1000 ) : m_AllocateNodeCount(0), m_FreeNodeCount(0), m_FixedSizeAllocator( MaxNodes ), m_State( SEARCH_STATE_NOT_INITIALISED ), m_CurrentSolutionNode( NULL ), m_CancelRequest( false ) { } // call at any time to cancel the search and free up all the memory void CancelSearch() { m_CancelRequest = true; } // Set Start and goal states void SetStartAndGoalStates( UserState &Start, UserState &Goal ) { m_CancelRequest = false; m_Start = AllocateNode(); m_Goal = AllocateNode(); m_Start->m_UserState = Start; m_Goal->m_UserState = Goal; m_State = SEARCH_STATE_SEARCHING; // Initialise the AStar specific parts of the Start Node // The user only needs fill out the state information m_Start->g = 0; m_Start->h = m_Start->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState ); m_Start->f = m_Start->g + m_Start->h; m_Start->parent = 0; // Push the start node on the Open list m_OpenList.push_back( m_Start ); // heap now unsorted // Sort back element into heap push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); // Initialise counter for search steps m_Steps = 0; } // Advances search one step unsigned int SearchStep() { // Firstly break if the user has not initialised the search assert( (m_State > SEARCH_STATE_NOT_INITIALISED) && (m_State < SEARCH_STATE_INVALID) ); // Next I want it to be safe to do a searchstep once the search has succeeded... if( (m_State == SEARCH_STATE_SUCCEEDED) || (m_State == SEARCH_STATE_FAILED) ) { return m_State; } // Failure is defined as emptying the open list as there is nothing left to // search... // New: Allow user abort if( m_OpenList.empty() || m_CancelRequest ) { FreeAllNodes(); m_State = SEARCH_STATE_FAILED; return m_State; } // Incremement step count m_Steps ++; // Pop the best node (the one with the lowest f) Node *n = m_OpenList.front(); // get pointer to the node pop_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); m_OpenList.pop_back(); // Check for the goal, once we pop that we're done if( n->m_UserState.IsGoal( m_Goal->m_UserState ) ) { // The user is going to use the Goal Node he passed in // so copy the parent pointer of n m_Goal->parent = n->parent; // A special case is that the goal was passed in as the start state // so handle that here if( n != m_Start ) { //delete n; FreeNode( n ); // set the child pointers in each node (except Goal which has no child) Node *nodeChild = m_Goal; Node *nodeParent = m_Goal->parent; do { nodeParent->child = nodeChild; nodeChild = nodeParent; nodeParent = nodeParent->parent; } while( nodeChild != m_Start ); // Start is always the first node by definition } // delete nodes that aren't needed for the solution FreeUnusedNodes(); m_State = SEARCH_STATE_SUCCEEDED; return m_State; } else // not goal { // We now need to generate the successors of this node // The user helps us to do this, and we keep the new nodes in // m_Successors ... m_Successors.clear(); // empty vector of successor nodes to n // User provides this functions and uses AddSuccessor to add each successor of // node 'n' to m_Successors bool ret = n->m_UserState.GetSuccessors( this, n->parent ? &n->parent->m_UserState : NULL ); if( !ret ) { typename vector< Node * >::iterator successor; // free the nodes that may previously have been added for( successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ ) { FreeNode( (*successor) ); } m_Successors.clear(); // empty vector of successor nodes to n // free up everything else we allocated FreeAllNodes(); m_State = SEARCH_STATE_OUT_OF_MEMORY; return m_State; } // Now handle each successor to the current node ... for( typename vector< Node * >::iterator successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ ) { // The g value for this successor ... double newg = n->g + n->m_UserState.GetCost( (*successor)->m_UserState ); // Now we need to find whether the node is on the open or closed lists // If it is but the node that is already on them is better (lower g) // then we can forget about this successor // First linear search of open list to find node typename vector< Node * >::iterator openlist_result; for( openlist_result = m_OpenList.begin(); openlist_result != m_OpenList.end(); openlist_result ++ ) { if( (*openlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) ) { break; } } if( openlist_result != m_OpenList.end() ) { // we found this state on open if( (*openlist_result)->g <= newg ) { FreeNode( (*successor) ); // the one on Open is cheaper than this one continue; } } typename vector< Node * >::iterator closedlist_result; for( closedlist_result = m_ClosedList.begin(); closedlist_result != m_ClosedList.end(); closedlist_result ++ ) { if( (*closedlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) ) { break; } } if( closedlist_result != m_ClosedList.end() ) { // we found this state on closed if( (*closedlist_result)->g <= newg ) { // the one on Closed is cheaper than this one FreeNode( (*successor) ); continue; } } // This node is the best node so far with this particular state // so lets keep it and set up its AStar specific data ... (*successor)->parent = n; (*successor)->g = newg; (*successor)->h = (*successor)->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState ); (*successor)->f = (*successor)->g + (*successor)->h; // Remove successor from closed if it was on it if( closedlist_result != m_ClosedList.end() ) { // remove it from Closed FreeNode( (*closedlist_result) ); m_ClosedList.erase( closedlist_result ); } // Update old version of this node if( openlist_result != m_OpenList.end() ) { FreeNode( (*openlist_result) ); m_OpenList.erase( openlist_result ); // re-make the heap make_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); // make_heap rather than sort_heap is an essential bug fix // thanks to Mike Ryynanen for pointing this out and then explaining // it in detail. sort_heap called on an invalid heap does not work // sort_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); // assert( is_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ) ); } // heap now unsorted m_OpenList.push_back( (*successor) ); // sort back element into heap push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() ); } // push n onto Closed, as we have expanded it now m_ClosedList.push_back( n ); } // end else (not goal so expand) return m_State; // Succeeded bool is false at this point. } // User calls this to add a successor to a list of successors // when expanding the search frontier bool AddSuccessor( UserState &State ) { Node *node = AllocateNode(); if( node ) { node->m_UserState = State; m_Successors.push_back( node ); return true; } return false; } // Free the solution nodes // This is done to clean up all used Node memory when you are done with the // search void FreeSolutionNodes() { Node *n = m_Start; if( m_Start->child ) { do { Node *del = n; n = n->child; FreeNode( del ); del = NULL; } while( n != m_Goal ); FreeNode( n ); // Delete the goal } else { // if the start node is the solution we need to just delete the start and goal // nodes FreeNode( m_Start ); FreeNode( m_Goal ); } } // Functions for traversing the solution // Get start node UserState *GetSolutionStart() { m_CurrentSolutionNode = m_Start; if( m_Start ) { return &m_Start->m_UserState; } else { return NULL; } } // Get next node UserState *GetSolutionNext() { if( m_CurrentSolutionNode ) { if( m_CurrentSolutionNode->child ) { Node *child = m_CurrentSolutionNode->child; m_CurrentSolutionNode = m_CurrentSolutionNode->child; return &child->m_UserState; } } return NULL; } // Get end node UserState *GetSolutionEnd() { m_CurrentSolutionNode = m_Goal; if( m_Goal ) { return &m_Goal->m_UserState; } else { return NULL; } } // Step solution iterator backwards UserState *GetSolutionPrev() { if( m_CurrentSolutionNode ) { if( m_CurrentSolutionNode->parent ) { Node *parent = m_CurrentSolutionNode->parent; m_CurrentSolutionNode = m_CurrentSolutionNode->parent; return ... [truncated message content] |
From: Eric M. <eri...@us...> - 2007-04-08 19:34:04
|
Update of /cvsroot/xconq/xconq/x11 In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv18084/x11 Modified Files: Tag: BRANCH_MCAMPO_PATH xcmd.c xcutil.c Log Message: Add changelog (mcampo.README) for BRANCH_MCAMPO_PATH. Add files necessary for A* pathfinder. Modify kernel to accomodate pathfinder. Change capture and hit-unit behavior. Index: xcutil.c =================================================================== RCS file: /cvsroot/xconq/xconq/x11/xcutil.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.8.1 diff -C2 -d -r1.1.1.1 -r1.1.1.1.8.1 *** xcutil.c 21 Nov 2004 03:02:59 -0000 1.1.1.1 --- xcutil.c 8 Apr 2007 19:34:02 -0000 1.1.1.1.8.1 *************** *** 246,250 **** img->rawpalette[4 * (img->numcolors - 1)] = (1 << img->pixelsize) - 1; numbytes = img->h * rowbytes; ! img->rawcolrdata = xmalloc(numbytes); memset(img->rawcolrdata, '\0', numbytes); rp = img->rawcolrdata; --- 246,250 ---- img->rawpalette[4 * (img->numcolors - 1)] = (1 << img->pixelsize) - 1; numbytes = img->h * rowbytes; ! img->rawcolrdata = (char *) xmalloc(numbytes); memset(img->rawcolrdata, '\0', numbytes); rp = img->rawcolrdata; Index: xcmd.c =================================================================== RCS file: /cvsroot/xconq/xconq/x11/xcmd.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.8.1 diff -C2 -d -r1.1.1.1 -r1.1.1.1.8.1 *** xcmd.c 21 Nov 2004 03:02:59 -0000 1.1.1.1 --- xcmd.c 8 Apr 2007 19:34:01 -0000 1.1.1.1.8.1 *************** *** 876,880 **** unit = find_unit(map->argunitid); if (in_play(unit)) { ! if (impl_move_to(side, unit, x, y, 0)) { return; } else { --- 876,880 ---- unit = find_unit(map->argunitid); if (in_play(unit)) { ! if (impl_move_to(side, unit, NULL, x, y, 0)) { return; } else { |
From: Eric M. <eri...@us...> - 2007-04-08 19:34:03
|
Update of /cvsroot/xconq/xconq/tcltk In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv18084/tcltk Modified Files: Tag: BRANCH_MCAMPO_PATH tkcmd.c Log Message: Add changelog (mcampo.README) for BRANCH_MCAMPO_PATH. Add files necessary for A* pathfinder. Modify kernel to accomodate pathfinder. Change capture and hit-unit behavior. Index: tkcmd.c =================================================================== RCS file: /cvsroot/xconq/xconq/tcltk/tkcmd.c,v retrieving revision 1.3 retrieving revision 1.3.2.1 diff -C2 -d -r1.3 -r1.3.2.1 *** tkcmd.c 12 Jun 2005 22:10:39 -0000 1.3 --- tkcmd.c 8 Apr 2007 19:34:01 -0000 1.3.2.1 *************** *** 1077,1081 **** return; } ! if (impl_move_to(side, unit, x, y, 0)) { return; } else { --- 1077,1081 ---- return; } ! if (impl_move_to(side, unit, NULL, x, y, 0)) { return; } else { |
From: Eric M. <eri...@us...> - 2007-04-08 19:34:02
|
Update of /cvsroot/xconq/xconq In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv18084 Added Files: Tag: BRANCH_MCAMPO_PATH mcampo.README Log Message: Add changelog (mcampo.README) for BRANCH_MCAMPO_PATH. Add files necessary for A* pathfinder. Modify kernel to accomodate pathfinder. Change capture and hit-unit behavior. --- NEW FILE: mcampo.README --- BUG FIXES (unconditional): kernel/side.c:side_controls_side crash fixed kernel/unix.c warning implemented x11/xcutil.c explicit cast added kernel/mkroads.c, kernel/mkrivers.c, kernel/init.c: make sure that auxterrain is allocated properly kernel/actions.c obvious bug fixes kernel/task.c fixed several issues of following a null task->next fixed a do_construct_task bug: when a human players changes construction in a city, the new unit is created outside the city if possible (aircraft in the standard game), otherwise the city is idled; work on old incomplete units is never resumed. NEW FEATURES (#ifdef BRANCH_MCAMPO): kernel/plan.c:past_halfway_point only watch "important" materials kernel/read.c:interp_task fix path in move-to & occupy tasks kernel/ui.c:impl_move_to new argument [Unit *unit2] added if unit2 is non-null, occupy it if possible, otherwise move to an adjacent position kernel/conq.h #define BRANCH_MCAMPO kernel/unit.h new task member [void *argptr] kernel/world.h pathfinding interface enum move_to_state moved here from task.c, added new cases to handle pathfinding x11/xcmd.c, tcltk/tkcmd.c, curses/ccmd.c: pass NULL as new argument to impl_move_to kernel/move.c total_entry_cost no loger declared static kernel/task.c some code reorganization, see in particular do_single_move_subtask interface to path_find (called from do_approach_subtask) use computed path whenever possible kernel/pathfind.cc new file containing pathfinding code kernel/stlastar.hpp, kernel/fsa.hpp new files containing an implementation of the A* algorithm |
From: Eric M. <eri...@us...> - 2007-04-08 19:34:02
|
Update of /cvsroot/xconq/xconq/curses In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv18084/curses Modified Files: Tag: BRANCH_MCAMPO_PATH ccmd.c Log Message: Add changelog (mcampo.README) for BRANCH_MCAMPO_PATH. Add files necessary for A* pathfinder. Modify kernel to accomodate pathfinder. Change capture and hit-unit behavior. Index: ccmd.c =================================================================== RCS file: /cvsroot/xconq/xconq/curses/ccmd.c,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -d -r1.2 -r1.2.2.1 *** ccmd.c 6 Jun 2005 03:03:43 -0000 1.2 --- ccmd.c 8 Apr 2007 19:34:01 -0000 1.2.2.1 *************** *** 545,549 **** sprintf(spbuf, "Move %s to where?", unit_handle(dside, curunit)); if (ask_position(spbuf, &x, &y)) { ! if (impl_move_to(side, curunit, x, y, 0)) { return; } else { --- 545,549 ---- sprintf(spbuf, "Move %s to where?", unit_handle(dside, curunit)); if (ask_position(spbuf, &x, &y)) { ! if (impl_move_to(side, curunit, NULL, x, y, 0)) { return; } else { |
From: Eric M. <eri...@us...> - 2007-04-08 19:04:03
|
Update of /cvsroot/xconq/xconq/kernel In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv5559/kernel Modified Files: Tag: BRANCH_MCAMPO_PATH init.c mkrivers.c mkroads.c Log Message: Ensure that aux_terrain layers are allocated, and note this where appropriate. Index: init.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/init.c,v retrieving revision 1.11 retrieving revision 1.11.2.1 diff -C2 -d -r1.11 -r1.11.2.1 *** init.c 10 Jul 2005 13:28:37 -0000 1.11 --- init.c 8 Apr 2007 19:03:58 -0000 1.11.2.1 *************** *** 710,713 **** --- 710,724 ---- } } + + /* Make sure that auxterrain is allocated properly. + Massimo, 16 March 2007 */ + { + int t; + for_all_terrain_types(t) { + if (t_subtype(t) != cellsubtype) { + allocate_area_aux_terrain(t); + } + } + } } Index: mkrivers.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/mkrivers.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.8.1 diff -C2 -d -r1.1.1.1 -r1.1.1.1.8.1 *** mkrivers.c 21 Nov 2004 03:01:10 -0000 1.1.1.1 --- mkrivers.c 8 Apr 2007 19:03:58 -0000 1.1.1.1.8.1 *************** *** 47,51 **** keyval = c_number(symbol_value(intern_symbol(keyword_name(K_RIVER_X)))); for_all_terrain_types(t) { ! if (t_subtype_x(t) == keyval && !aux_terrain_defined(t)) { if (t_is_border(t)) { make_up_river_borders(t); --- 47,54 ---- keyval = c_number(symbol_value(intern_symbol(keyword_name(K_RIVER_X)))); for_all_terrain_types(t) { ! if (t_subtype_x(t) == keyval ! /* See init.c:721; Massimo, 19 March 2007 */ ! /* && !aux_terrain_defined(t) */ ! ) { if (t_is_border(t)) { make_up_river_borders(t); Index: mkroads.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/mkroads.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.8.1 diff -C2 -d -r1.1.1.1 -r1.1.1.1.8.1 *** mkroads.c 21 Nov 2004 03:01:10 -0000 1.1.1.1 --- mkroads.c 8 Apr 2007 19:03:58 -0000 1.1.1.1.8.1 *************** *** 46,50 **** for_all_terrain_types(t) { if (t_is_connection(t) ! && !aux_terrain_defined(t) && t_subtype_x(t) == keyval) { roadtype = t; --- 46,51 ---- for_all_terrain_types(t) { if (t_is_connection(t) ! /* See init.c:721; Massimo, 19 March 2007 */ ! /* && !aux_terrain_defined(t) */ && t_subtype_x(t) == keyval) { roadtype = t; |
From: Eric M. <eri...@us...> - 2007-04-08 18:47:13
|
Update of /cvsroot/xconq/xconq/kernel In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv31089/kernel Modified Files: Tag: BRANCH_MCAMPO_PATH actions.c Log Message: Fix some issues with application of coatings by units. Index: actions.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/actions.c,v retrieving revision 1.23 retrieving revision 1.23.2.1 diff -C2 -d -r1.23 -r1.23.2.1 *** actions.c 2 Jul 2005 20:14:22 -0000 1.23 --- actions.c 8 Apr 2007 18:47:01 -0000 1.23.2.1 *************** *** 3990,3994 **** oldval = aux_terrain_at(x, y, t); /* Interpret "dir" as depth of coating to add. */ ! newval = min(oldval + dir, tt_coat_max(terrain_at(x, y), t)); set_aux_terrain_at(x, y, t, newval); break; --- 3990,3995 ---- oldval = aux_terrain_at(x, y, t); /* Interpret "dir" as depth of coating to add. */ ! /* Fix indices of tt_coat_max. Massimo, 16 March 2007 */ ! newval = min(oldval + dir, tt_coat_max(t, terrain_at(x, y))); set_aux_terrain_at(x, y, t, newval); break; *************** *** 4102,4106 **** newval = max(oldval - dir, 0); /* If newval drops below the min coating depth, coating will vanish. */ ! if (newval < tt_coat_min(terrain_at(x, y), t)) newval = 0; set_aux_terrain_at(x, y, t, newval); --- 4103,4108 ---- newval = max(oldval - dir, 0); /* If newval drops below the min coating depth, coating will vanish. */ ! /* Fix indices of tt_coat_min. Massimo, 16 March 2007 */ ! if (newval < tt_coat_min(t, terrain_at(x, y))) newval = 0; set_aux_terrain_at(x, y, t, newval); *************** *** 4121,4131 **** distribute_material(unit2, m, excess); } } - /* Then try to fill up unit2 again with the remaining excess. */ - space = um_storage_x(unit2->type, m) - unit2->supply[m]; - /* The check for available space is redundant now, but will be needed - in the future when distribute_material has been improved. */ - unit2->supply[m] += min(excess, space); - /* Let everybody see what has happened. */ for_all_sides(side) { --- 4123,4134 ---- distribute_material(unit2, m, excess); } + /* Extend for_all_material_types to include the following stuff. + Massimo, 16 March 2007 */ + /* Then try to fill up unit2 again with the remaining excess. */ + space = um_storage_x(unit2->type, m) - unit2->supply[m]; + /* The check for available space is redundant now, but will be needed + in the future when distribute_material has been improved. */ + unit2->supply[m] += min(excess, space); } /* Let everybody see what has happened. */ for_all_sides(side) { |
From: Eric M. <eri...@us...> - 2007-04-08 18:37:13
|
Update of /cvsroot/xconq/xconq/kernel In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv26589/kernel Modified Files: Tag: BRANCH_MCAMPO_PATH task.c Log Message: Fix for a 'do_construct_task' bug. Create inside city, when possible. Index: task.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/task.c,v retrieving revision 1.14.2.1 retrieving revision 1.14.2.2 diff -C2 -d -r1.14.2.1 -r1.14.2.2 *** task.c 8 Apr 2007 18:30:45 -0000 1.14.2.1 --- task.c 8 Apr 2007 18:37:06 -0000 1.14.2.2 *************** *** 1495,1499 **** --- 1495,1511 ---- // If so, then decrement the construction run length, // clear the creation ID, and push a build task, if necessary. + + // Else, we search for an incomplete unit of the desired type + // and work at its completion. Massimo, 20 March 2007 creation = find_unit(constructor->creation_id); + if (!in_play(creation)) { + creation = find_unit_to_complete(constructor, task); + if (in_play(creation)) { + // Fix task parameters + task->args[2] = creation->transport ? creation->transport->id : -1; + task->args[3] = creation->x; + task->args[4] = creation->y; + } + } if (in_play(creation)) { constructor->creation_id = -1; *************** *** 1514,1519 **** return TASK_IS_INCOMPLETE; } ! // Else, we try to proceed with creating an unit ! // in the desired cell or transport. // If research or development is needed, then we should not be in this code. if (!side_can_build(side, uc)) --- 1526,1530 ---- return TASK_IS_INCOMPLETE; } ! // If research or development is needed, then we should not be in this code. if (!side_can_build(side, uc)) *************** *** 1522,1525 **** --- 1533,1540 ---- if (!has_enough_tooling(constructor, uc)) return do_toolup_subtask(constructor, uc); + + // Else, we try to proceed with creating an unit + // in the desired transport, inside self, or in the desired cell. + // If transport is valid, then try creating in it. if (in_play(transport)) { *************** *** 1530,1535 **** } } ! // Else, try creating in designated cell. ! else { if (valid(rslt = can_create_at(constructor, constructor, uc, x, y))) { --- 1545,1558 ---- } } ! ! // Else, try creating in self. Massimo, 20 March 2007 ! if (in_play(constructor)) { ! if (valid(rslt = ! can_create_in(constructor, constructor, uc, constructor))) { ! prep_create_in_action(constructor, constructor, uc, constructor); ! return TASK_PREPPED_ACTION; ! } ! ! // Else, try creating in designated cell. if (valid(rslt = can_create_at(constructor, constructor, uc, x, y))) { |
From: Eric M. <eri...@us...> - 2007-04-08 18:31:20
|
Update of /cvsroot/xconq/xconq/kernel In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv24497/kernel Modified Files: Tag: BRANCH_MCAMPO_PATH task.c Log Message: Fix crash in 'do_repair_self_subtask'. Index: task.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/task.c,v retrieving revision 1.14 retrieving revision 1.14.2.1 diff -C2 -d -r1.14 -r1.14.2.1 *** task.c 17 Sep 2005 16:21:22 -0000 1.14 --- task.c 8 Apr 2007 18:30:45 -0000 1.14.2.1 *************** *** 1587,1598 **** && (uu_auto_repair_range(u2, u) >= distance(tasks2->args[0], tasks2->args[1], tx, ty))) ! tasks2 = tasks2->next; if ((TASK_MOVE_TO == tasks2->type) && (uu_repair_range(u2, u) >= distance(tasks2->args[0], tasks2->args[1], tx, ty))) ! tasks2 = tasks2->next; // If 'occupy' task, then inspect closer. if (TASK_OCCUPY == tasks2->type) ! tasks2 = tasks2->next; // If not 'repair' task, then skip. if (TASK_REPAIR != tasks2->type) --- 1587,1598 ---- && (uu_auto_repair_range(u2, u) >= distance(tasks2->args[0], tasks2->args[1], tx, ty))) ! { tasks2 = tasks2->next; if (!tasks2) continue; }; if ((TASK_MOVE_TO == tasks2->type) && (uu_repair_range(u2, u) >= distance(tasks2->args[0], tasks2->args[1], tx, ty))) ! { tasks2 = tasks2->next; if (!tasks2) continue; }; // If 'occupy' task, then inspect closer. if (TASK_OCCUPY == tasks2->type) ! { tasks2 = tasks2->next; if (!tasks2) continue; }; // If not 'repair' task, then skip. if (TASK_REPAIR != tasks2->type) |
From: Eric M. <eri...@us...> - 2007-04-08 18:26:54
|
Update of /cvsroot/xconq/xconq/kernel In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv22501/kernel Modified Files: Tag: BRANCH_MCAMPO_PATH unix.c Log Message: Warn if homedir not found on Unix. Index: unix.c =================================================================== RCS file: /cvsroot/xconq/xconq/kernel/unix.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.8.1 diff -C2 -d -r1.1.1.1 -r1.1.1.1.8.1 *** unix.c 21 Nov 2004 03:01:26 -0000 1.1.1.1 --- unix.c 8 Apr 2007 18:26:53 -0000 1.1.1.1.8.1 *************** *** 207,212 **** /* Try to ensure that the directory exists. */ if (access(homedir, F_OK) != 0) { ! mkdir(homedir, 0755); ! /* (should warn of problems) */ } return homedir; --- 207,214 ---- /* Try to ensure that the directory exists. */ if (access(homedir, F_OK) != 0) { ! if (mkdir(homedir, 0755) != 0) { ! /* warn of problems */ ! init_warning("could not create the directory %s", homedir); ! } } return homedir; |
From: Eric M. <eri...@us...> - 2006-06-02 16:59:19
|
Update of /cvsroot/xconq/xconq/cvs_hist In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv23296 Modified Files: MAPPINGS Log Message: Update mappings to show refactoring due to GDL serialization support. Index: MAPPINGS =================================================================== RCS file: /cvsroot/xconq/xconq/cvs_hist/MAPPINGS,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** MAPPINGS 30 May 2006 02:49:03 -0000 1.16 --- MAPPINGS 2 Jun 2006 16:59:17 -0000 1.17 *************** *** 2,12 **** --- 2,17 ---- kernel/actions.c ==== MIGRATE ====> [sourceforge.net] + kernel/ai.c ==== REFACTOR ====> src/gdl/side/side.cc kernel/ai.c ==== REFACTOR ====> src/gdl/unit/goal.cc kernel/ai.c ==== MIGRATE ====> [sourceforge.net] + kernel/ai.h ==== REFACTOR ====> src/gdl/side/side.h + kernel/ai.h ==== MIGRATE ====> [sourceforge.net] + kernel/config.h ==== REFACTOR ====> src/include/gdl/world.h kernel/config.h ==== MIGRATE ====> [sourceforge.net] kernel/conq.h ==== REFACTOR ====> src/include/gdl/gamearea/world.h + kernel/conq.h ==== REFACTOR ====> src/include/gdl/history.h kernel/conq.h ==== REFACTOR ====> src/include/gdl/module.h kernel/conq.h ==== REFACTOR ====> src/include/gdl/namer.h *************** *** 14,20 **** --- 19,27 ---- kernel/conq.h ==== REFACTOR ====> src/include/gdl/side/unitview.h kernel/conq.h ==== REFACTOR ====> src/include/gdl/types.h + kernel/conq.h ==== REFACTOR ====> src/include/gdl/ui.h kernel/conq.h ==== REFACTOR ====> src/include/gdl/unit/goal.h kernel/conq.h ==== REFACTOR ====> src/include/gdl/unit/task.h kernel/conq.h ==== REFACTOR ====> src/include/gdl/unit/unit.h + kernel/conq.h ==== REFACTOR ====> src/include/util/memory.h kernel/conq.h ==== MIGRATE ====> [sourceforge.net] *************** *** 87,92 **** --- 94,102 ---- kernel/nlang.c ==== REFACTOR ====> src/gdl/desc.cc kernel/nlang.c ==== REFACTOR ====> src/gdl/dir.cc + kernel/nlang.c ==== REFACTOR ====> src/gdl/history.cc kernel/nlang.c ==== REFACTOR ====> src/gdl/side/side.cc + kernel/nlang.c ==== REFACTOR ====> src/gdl/unit/pastunit.cc kernel/nlang.c ==== REFACTOR ====> src/gdl/unit/task.cc + kernel/nlang.c ==== REFACTOR ====> src/gdl/unit/unit.cc kernel/nlang.c ==== MIGRATE ====> [sourceforge.net] *************** *** 191,194 **** --- 201,207 ---- kernel/task.c ==== MIGRATE ====> [sourceforge.net] + kernel/tp.h ==== REFACTOR ====> src/include/gdl/kernel.h + kernel/tp.h ==== MIGRATE ====> [sourceforge.net] + kernel/types.c ==== REFACTOR ====> src/gdl/types.cc kernel/types.c ==== MIGRATE ====> [sourceforge.net] *************** *** 234,237 **** --- 247,292 ---- kernel/world.h ==== MIGRATE ====> [sourceforge.net] + kernel/write.c ==== MIGRATE ====> src/gdl/gamearea/area.cc + kernel/write.c ==== MIGRATE ====> src/gdl/gamearea/layers.cc + kernel/write.c ==== MIGRATE ====> src/gdl/gvars.cc + kernel/write.c ==== MIGRATE ====> src/gdl/history.cc + kernel/write.c ==== MIGRATE ====> src/gdl/lisp.cc + kernel/write.c ==== MIGRATE ====> src/gdl/media/imf.cc + kernel/write.c ==== MIGRATE ====> src/gdl/module.cc + kernel/write.c ==== MIGRATE ====> src/gdl/namer.cc + kernel/write.c ==== MIGRATE ====> src/gdl/player.cc + kernel/write.c ==== MIGRATE ====> src/gdl/score.cc + kernel/write.c ==== MIGRATE ====> src/gdl/side/cellview.cc + kernel/write.c ==== MIGRATE ====> src/gdl/side/doctrine.cc + kernel/write.c ==== MIGRATE ====> src/gdl/side/side.cc + kernel/write.c ==== MIGRATE ====> src/gdl/side/sorder.cc + kernel/write.c ==== MIGRATE ====> src/gdl/tables.cc + kernel/write.c ==== MIGRATE ====> src/gdl/types.cc + kernel/write.c ==== MIGRATE ====> src/gdl/unit/goal.cc + kernel/write.c ==== MIGRATE ====> src/gdl/unit/plan.cc + kernel/write.c ==== MIGRATE ====> src/gdl/unit/task.cc + kernel/write.c ==== MIGRATE ====> src/gdl/unit/unit.cc + kernel/write.c ==== MIGRATE ====> src/gdl/world.cc + kernel/write.c ==== MIGRATE ====> src/include/gdl/gamearea/area.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/gamearea/layers.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/gvars.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/history.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/lisp.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/media/imf.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/module.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/namer.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/player.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/score.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/side/cellview.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/side/doctrine.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/side/side.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/side/sorder.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/tables.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/types.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/unit/goal.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/unit/plan.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/unit/task.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/unit/unit.h + kernel/write.c ==== MIGRATE ====> src/include/gdl/world.h kernel/write.c ==== MIGRATE ====> src/util/fs.cc kernel/write.c ==== MIGRATE ====> [sourceforge.net] |
From: Eric M. <eri...@us...> - 2006-06-02 16:58:40
|
Update of /cvsroot/xconq/xconq/src/include/gdl/side In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv23113/side Modified Files: cellview.h doctrine.h side.h sorder.h Log Message: Add CVS serialization support. Fix copyrights. Index: side.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/side/side.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** side.h 30 May 2006 02:34:14 -0000 1.1 --- side.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 60,66 **** --- 60,75 ---- (s != indepside ? m_treasury(m) : g_indepside_has_treasury() ? m_treasury(m) : FALSE) + //! Is side running an AI locally? + #define side_has_local_ai(s) ((s)->ai != NULL) + //! Is given unit being tracked by given side? #define side_tracking_unit(side,unit) (side_in_set((side), (unit)->tracking)) + //! How many attacks for given side with given attacker against given defender? + #define side_atkstats(s,a,d) ((s)->atkstats[a] ? ((s)->atkstats[a])[d] : 0) + + //! How many hits for given side with given attacker against given defender? + #define side_hitstats(s,a,d) ((s)->hitstats[a] ? ((s)->hitstats[a])[d] : 0) + // Function Macros: Game Area Layer Accessors *************** *** 94,97 **** --- 103,115 ---- for (v = sidelist; v != NULL; v = v->next) + //! Iterate over player 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) + + //! Iterate over all units on side. + #define for_all_side_units(s,v) \ + for (v = (s)->unithead->next; v != (s)->unithead; v = v->next) + NAMESPACE_XCONQ_BEGIN NAMESPACE_GDL_BEGIN *************** *** 424,427 **** --- 442,476 ---- } Side; + //! AI operation hooks. + typedef struct a_ai_op { + //! Name of AI. + char *name; + //! Help text about AI. + char *help; + //! ?? + int (*to_test_compat)(void); + //! Hook: Initialize AI for given side. + void (*to_init)(Side *side); + //! Hook: Perform start-of-turn analysis/planning. + void (*to_init_turn)(Side *side); + //! Hook: Choose a plan for given unit. + void (*to_decide_plan)(Side *side, Unit *unit); + //! Hook: React to outcome of executed unit task. + void (*to_react_to_task_result)( + Side *side, Unit *unit, Task *task, TaskOutcome rslt); + //! Hook: React to new side joining the game. + void (*to_react_to_new_side)(Side *side, Side *side2); + //! Hook: Adjust an unit's plan during turn. + int (*to_adjust_plan)(Side *side, Unit *unit); + //! Hook: Finalize action for turn. + void (*to_finish_movement)(Side *side); + //! Hook: Save state. + Obj *(*to_save_state)(Side *side); + //! Hook: Get ID of AI region at given coordinates. + int (*region_at)(Side *side, int x, int y); + //! Hook: Get designator of AI at given coordinates. + char *(*at_desig)(Side *side, int x, int y); + } AI_ops; + //! Parameter box containing unit and side. struct ParamBoxUnitSide : public ParamBoxUnit { *************** *** 469,472 **** --- 518,524 ---- extern int numtotsides; + //! The array of all possible AI operation hooks. + extern AI_ops *all_ai_ops; + // Global Variables: Uniques *************** *** 482,485 **** --- 534,541 ---- extern int nextsideid; + // Global Variables: Behavior Options + + extern int tmpcompress; + // Global Variables: Buffers *************** *** 601,604 **** --- 657,672 ---- extern void interp_side_value_list(short *arr, Obj *lis); + //! Serialize side's AI state to GDL. + extern void ai_save_state(Side *side); + //! Serialize side's views layers to GDL. + extern void write_side_view(Side *side, int compress); + //! Serialize side properties to GDL. + extern void write_side_properties(Side *side); + //! Serialize sides to GDL. + extern void write_sides(struct a_module *module); + //! Serialize list of side-value pairs to GDL. + extern void write_side_value_list( + char *name, short *arr, int dflt, int addnewline); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: cellview.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/side/cellview.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** cellview.h 30 May 2006 02:34:14 -0000 1.1 --- cellview.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 258,274 **** // Game Area View Layer Accessors 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); --- 258,317 ---- // Game Area View Layer Accessors + //! Get cell value from terrain views layer. + extern int fn_terrain_view(int x, int y); + //! Get cell value from terrain view dates layer. + extern int fn_terrain_view_date(int x, int y); + //! Get cell value from aux terrain views layer. + extern int fn_aux_terrain_view(int x, int y); + //! Get cell value from aux terrain view dates layer. + extern int fn_aux_terrain_view_date(int x, int y); + //! Get cell value from material views layer. + extern int fn_material_view(int x, int y); + //! Get cell value from material view dates layer. + extern int fn_material_view_date(int x, int y); + //! Get cell value from temp views layer. + extern int fn_temp_view(int x, int y); + //! Get cell value from temp view dates layer. + extern int fn_temp_view_date(int x, int y); + //! Get cell value from cloud views layer. + extern int fn_cloud_view(int x, int y); + //! Get cell value from cloud bottom views layer. + extern int fn_cloud_bottom_view(int x, int y); + //! Get cell value from cloud top/height views layer. + extern int fn_cloud_height_view(int x, int y); + //! Get cell value from cloud view dates layer. + extern int fn_cloud_view_date(int x, int y); + //! Get cell value from wind views layer. + extern int fn_wind_view(int x, int y); + //! Get cell value from wind view dates layer. + extern int fn_wind_view_date(int x, int y); + + //! Set cell value in terrain views layer. extern void fn_set_terrain_view(int x, int y, int val); ! //! Set cell value in terrain view dates layer. extern void fn_set_terrain_view_date(int x, int y, int val); + //! Set cell value in aux terrain views layer. + extern void fn_set_aux_terrain_view(int x, int y, int val); + //! Set cell value in aux terrain view dates layer. extern void fn_set_aux_terrain_view_date(int x, int y, int val); + //! Set cell value in material views layer. extern void fn_set_material_view(int x, int y, int val); + //! Set cell value in terrain view dates layer. extern void fn_set_material_view_date(int x, int y, int val); + //! Set cell value in temp views layer. extern void fn_set_temp_view(int x, int y, int val); + //! Set cell value in temp view dates layer. extern void fn_set_temp_view_date(int x, int y, int val); + //! Set cell value in cloud views layer. extern void fn_set_cloud_view(int x, int y, int val); + //! Set cell value in cloud bottom views layer. extern void fn_set_cloud_bottom_view(int x, int y, int val); + //! Set cell value in cloud height/top views layer. extern void fn_set_cloud_height_view(int x, int y, int val); + //! Set cell value in cloud view dates layer. extern void fn_set_cloud_view_date(int x, int y, int val); + //! Set cell value in wind views layer. extern void fn_set_wind_view(int x, int y, int val); + //! Set cell value in wind view dates layer. extern void fn_set_wind_view_date(int x, int y, int val); *************** *** 287,297 **** --- 330,346 ---- // GDL I/O + //! Read side view layer from GDL. extern void read_view_layer( Side *side, Obj *contents, void (*setter)(int, int, int)); + //! Read side aux terrain view layer from GDL. extern void read_aux_terrain_view_layer( Side *side, Obj *contents, void (*setter)(int, int, int)); + //! Read side material view layer from GDL. extern void read_material_view_layer( Side *side, Obj *contents, void (*setter)(int, int, int)); + //! Serialize side view layer to GDL. + extern void write_one_side_view_layer(int propkey, int (*fn)(int x, int y)); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: doctrine.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/side/doctrine.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** doctrine.h 30 May 2006 02:34:14 -0000 1.2 --- doctrine.h 2 Jun 2006 16:58:34 -0000 1.3 *************** *** 119,122 **** --- 119,125 ---- extern void interp_doctrine(Obj *form); + //! Serialize side doctrines to GDL. + extern void write_doctrines(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: sorder.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/side/sorder.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** sorder.h 30 May 2006 02:34:14 -0000 1.1 --- sorder.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 104,107 **** --- 104,110 ---- extern void interp_standing_order(Side *side, Obj *form); + //! Serialize standing orders to GDL. + extern void write_standing_orders(Side *side); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END |
From: Eric M. <eri...@us...> - 2006-06-02 16:58:40
|
Update of /cvsroot/xconq/xconq/src/include/gdl/gamearea In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv23113/gamearea Modified Files: area.h feature.h layers.h Log Message: Add CVS serialization support. Fix copyrights. Index: feature.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/gamearea/feature.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** feature.h 29 May 2006 19:24:54 -0000 1.1 --- feature.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 85,88 **** --- 85,93 ---- } Feature; + // Global Variables + + //! List of features. + extern Feature *featurelist; + // Queries Index: area.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/gamearea/area.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** area.h 29 May 2006 19:24:54 -0000 1.1 --- area.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 330,333 **** --- 330,343 ---- extern void interp_area(Obj *form); + //! Serialize game areas to GDL. + /*! + Write info about the area in the world. This code uses run-length + encoding to reduce the size of each written layer as much as + possible. Note also that each layer is written as a separate form, + so that the Lisp reader doesn't have to read really large forms + back in. + */ + extern void write_areas(struct a_module *module); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: layers.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/gamearea/layers.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** layers.h 29 May 2006 19:24:54 -0000 1.1 --- layers.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 63,66 **** --- 63,69 ---- #define CALM (0) + //! Cell has no user. + #define NOUSER (0) + // Function Macros: Queries *************** *** 144,147 **** --- 147,153 ---- (aux_terrain_defined(c) ? (aux_terrain_at(x, y, c) & (1 << (dir))) : FALSE) + //! Get cell value from features layer. + #define raw_feature_at(x,y) aref(area.features, x, y) + //! Get cell value from elevations layer. #define elev_at(x,y) aref(area.elevations, x, y) *************** *** 168,171 **** --- 174,183 ---- #define people_side_at(x,y) aref(area.peopleside, x, y) + //! Get cell value from side control layer. + #define control_side_at(x,y) aref(area.controlside, x, y) + + //! Get cell value from cell users layer. + #define user_at(x, y) aref(area.user, x, y) + //! Get cell value from scratch layer 1. #define tmp1_at(x,y) aref(area.tmp1, x, y) *************** *** 260,263 **** --- 272,302 ---- // Game Area Layers Accessors + //! Get cell value from terrain layer. + extern int fn_terrain_at(int x, int y); + //! Get cell value from aux terrains layers. + extern int fn_aux_terrain_at(int x, int y); + //! Get cell value from features layer. + extern int fn_feature_at(int x, int y); + //! Get cell value from elevations layer. + extern int fn_elevation_at(int x, int y); + //! Get cell value from people sides layer. + extern int fn_people_side_at(int x, int y); + //! Get cell value from side control layer. + extern int fn_control_side_at(int x, int y); + //! Get cell value from materials layers. + extern int fn_material_at(int x, int y); + //! Get cell value from temperatures layer. + extern int fn_temperature_at(int x, int y); + //! Get cell value from clouds layer. + extern int fn_raw_cloud_at(int x, int y); + //! Get cell value from cloud bottoms layer. + extern int fn_raw_cloud_bottom_at(int x, int y); + //! Get cell value from cloud tops/heights layer. + extern int fn_raw_cloud_height_at(int x, int y); + //! Get cell value from winds layer. + extern int fn_raw_wind_at(int x, int y); + //! Get cell value from cell users layer. + extern int fn_user_at(int x, int y); + //! Set cell in terrain layer. extern void fn_set_terrain_at(int x, int y, int val); *************** *** 366,369 **** --- 405,445 ---- extern void fill_in_users(Obj *contents); + //! Encode and write textual run-length encodings. + /*! + This is a generalized routine to do run-length-encoding of area + layers. It uses hook fns to acquire data at a point and an + optional translator to do any last-minute fixing. It can use + either a char or numeric encoding, depending on the expected range + of values. + */ + extern void write_rle( + int (*datafn)(int, int), + int lo, int hi, + int (*translator)(int), + int compress); + + //! Serialize terrain layer to GDL. + extern void write_area_terrain(int compress); + //! Serialize aux terrain layers to GDL. + extern void write_area_aux_terrain(int compress); + //! Serialize features layer to GDL. + extern void write_area_features(int compress); + //! Serialize elevations layer to GDL. + extern void write_area_elevations(int compress); + //! Serialize people sides layer to GDL. + extern void write_area_people_sides(int compress); + //! Serialize control sides layer to GDL. + extern void write_area_control_sides(int compress); + //! Serialize materials layers to GDL. + extern void write_area_materials(int compress); + //! Serialize temperatures layer to GDL. + extern void write_area_temperatures(int compress); + //! Serialize clouds layers to GDL. + extern void write_area_clouds(int compress); + //! Serialize winds layer to GDL. + extern void write_area_winds(int compress); + //! Serialize cell users layer to GDL. + extern void write_area_users(int compress); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END |
From: Eric M. <eri...@us...> - 2006-06-02 16:58:38
|
Update of /cvsroot/xconq/xconq/src/include/gdl In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv23113 Modified Files: gvars.h history.h kernel.h lisp.h module.h namer.h pact.h player.h score.h tables.h types.h ui.h world.h Log Message: Add CVS serialization support. Fix copyrights. Index: world.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/world.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** world.h 29 May 2006 20:11:12 -0000 1.1 --- world.h 2 Jun 2006 16:58:33 -0000 1.2 *************** *** 126,129 **** --- 126,132 ---- extern int daynight; + //! True if the area is to be saved to a different size than it is now. + extern int doreshape; + // Queries *************** *** 146,149 **** --- 149,158 ---- extern void interp_world(Obj *form); + //! Compute and return the corresponding point in an area being reshaped. + extern int reshaped_point(int x1, int y1, int *x2p, int *y2p); + + //! Serialize world to GDL. + extern void write_world(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: module.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/module.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** module.h 27 May 2006 17:31:34 -0000 1.1 --- module.h 2 Jun 2006 16:58:33 -0000 1.2 *************** *** 6,11 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2003-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// + Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 225,228 **** --- 226,235 ---- extern Module *curmodule; + //! File being written to. + extern FILE *wfp; + + //! Module used for reshaping game area output. + extern Module *reshaper; + // Global Variables: Validation *************** *** 232,235 **** --- 239,245 ---- // Global Variables: Game State + //! True, if game in safe state for saving. + extern int gamestatesafe; + //! True, if game will start in middle of a turn. extern int midturnrestore; *************** *** 243,246 **** --- 253,261 ---- extern PackedBoolTable *G_advances_synopsis; + // Global Variables: Buffers + + //! Buffer for shortest names. + extern char *shortestbuf; + // Queries *************** *** 359,362 **** --- 374,395 ---- extern void do_module_variants(Module *module, Obj *lis); + //! Preparation and preallocation for writing. + extern void init_write(void); + + /* + NOTE: 'write_entire_game_state' is forward declared in an "earlier" + namespace. The declaration eventually should be moved here. + */ + + //! True, if any actual reshaping is required. + extern int reshape_the_output(Module *module); + + //! Serialize game module to GDL. + /*! + Given a game module telling what is in the module, write out a file + containing the requested content. Return true if all went OK. + */ + extern int write_game_module(Module *module, char *fname); + #if (0) // Temp disable. *************** *** 377,381 **** extern void clear_game_modules(void); extern void init_module_reshape(Module *module); - extern int reshape_the_output(Module *module); extern int valid_reshape(Module *module); extern char *saved_game_filename(void); --- 410,413 ---- Index: player.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/player.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** player.h 27 May 2006 23:31:34 -0000 1.1 --- player.h 2 Jun 2006 16:58:33 -0000 1.2 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 116,119 **** --- 116,124 ---- extern void interp_player(Obj *form); + //! Serialize player to GDL. + extern void write_player(struct a_player *player); + //! Serialize players to GDL. + extern void write_players(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: ui.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/ui.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** ui.h 30 May 2006 02:50:19 -0000 1.2 --- ui.h 2 Jun 2006 16:58:33 -0000 1.3 *************** *** 56,68 **** NAMESPACE_GDL_BEGIN ! // Global Functions: Notification ! //! Notify given side of something via UI. extern void notify(Side *side, char *str, ...); //! Announce amount of progress in reading a GDL form. extern void announce_read_progress(void); ! // Global Functions: Debug/Trace //! Print GDL form via UI. --- 56,76 ---- NAMESPACE_GDL_BEGIN ! // Notifications ! //! Notify given side of something. extern void notify(Side *side, char *str, ...); + //! Notify all sides of something. + extern void notify_all(char *str, ...); + //! Announce amount of progress in reading a GDL form. extern void announce_read_progress(void); ! // Queries ! ! //! Does the side have an active display associated with it? ! extern int active_display(Side *side); ! ! // Debugging/Tracing //! Print GDL form via UI. *************** *** 72,76 **** extern void end_printing_forms(void); ! // Global Functions: Status Displays //! Ask UI to update display of given unit. --- 80,85 ---- extern void end_printing_forms(void); ! // Status Displays ! //! Ask UI to update display of given unit. *************** *** 78,84 **** --- 87,98 ---- //! Ask UI to update display of given cell. extern void update_cell_display(Side *side, int x, int y, int flags); + //! Ask UI to update display of given event. + extern void update_event_display(Side *side, struct a_histevent *hevt, int rightnow); //! Flush display buffers for given side. extern void flush_display_buffers(Side *side); + //! Play any movies associated with event. + extern void play_event_movies(Side *side, struct a_histevent *hevt); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: score.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/score.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** score.h 28 May 2006 18:10:41 -0000 1.1 --- score.h 2 Jun 2006 16:58:33 -0000 1.2 *************** *** 93,96 **** --- 93,104 ---- extern int numscorekeepers; + //! Number of scores being kept. + extern int numscores; + + //! Update any scores after action? + extern int any_post_action_scores; + //! Update any scores after event? + extern int any_post_event_scores; + // Queries *************** *** 108,111 **** --- 116,122 ---- extern void interp_scorekeeper(Obj *form); + //! Serialize scorekeeper to GDL. + extern void write_scorekeepers(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: kernel.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/kernel.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** kernel.h 30 May 2006 02:50:19 -0000 1.2 --- kernel.h 2 Jun 2006 16:58:33 -0000 1.3 *************** *** 44,58 **** extern int numremotes; // Global Variables: Game State //! True, if at end of game. extern int endofgame; // Global Variables: Notification ! //! Warnings suppressed flag. extern int warnings_suppressed; ! // Global Variables: Game Setup //! Return GDL list of default world synthesis methods. --- 44,81 ---- extern int numremotes; + //! Temporary remote id. + extern int tmprid; + // Global Variables: Game State + //! True, if before start of game. + extern int beforestart; + //! True, if at end of game. extern int endofgame; + //! True, if synchronizing debugging state. + extern int debugging_state_sync; + + //! Real time at which game was started. + extern time_t game_start_in_real_time; + + //! True, if post event scoring is needed. + extern int need_post_event_scores; + // Global Variables: Notification ! //! Flag: warnings suppressed. extern int warnings_suppressed; ! // Network ! ! //! Add string to network packet. ! extern void add_to_packet(char *str); ! ! //! Finalize packet write. ! extern void flush_write(void); ! ! // Game Setup //! Return GDL list of default world synthesis methods. Index: lisp.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/lisp.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** lisp.h 27 May 2006 02:55:14 -0000 1.4 --- lisp.h 2 Jun 2006 16:58:33 -0000 1.5 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2004-2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2004-2006 Eric A. McDonald *************** *** 53,56 **** --- 53,61 ---- #define CONTEXTSIZE 129 + // Function Macros: Queries + + //! Get keyword name from key value. + #define key(x) (keyword_name(x)) + // Function Macros: Validation *************** *** 291,294 **** --- 296,302 ---- extern int equal(Obj *x, Obj *y); + //! Is string not its default value? + extern int string_not_default(char *str, char *dflt); + // Queries: Attribution *************** *** 380,383 **** --- 388,394 ---- extern void set_cdr(Obj *x, Obj *v); + //! Replace GDL list item where key is matched. + extern Obj *replace_at_key(Obj *lis, char *key, Obj *newval); + //! Remove element from list. extern Obj *remove_from_list(Obj *element, Obj *lis); *************** *** 487,490 **** --- 498,573 ---- extern void interp_long_array(long *arr, Obj *lis, int n); + //! Convert symbol name to its GDL escaped form. + /*! \bug Potential buffer overflow. */ + extern char *escaped_symbol(char *str); + //! Convert string to its GDL escaped form. + /*! + Note that this works correctly on NULL strings, turning them into + strings of length 0. + */ + /*! \bug Potential buffer overflow. */ + extern char *escaped_string(char *str); + //! Safely convert string to its GDL escaped form. + /*! + The escaped_string() function makes a dangerous assumption about + the length of an escaped (or even unescaped) string being less than + the BUFSIZE, which is the size of escapedthingbuf. + safe_escaped_string() is slightly less efficient, but avoids this + assumption. Do note, however, that safe_escaped_string() can result + in a memory leak, if the caller does not free the result after + using it. + */ + extern char *safe_escaped_string(char *str, int len); + + //! Serialize start-of-form token to GDL. + extern void start_form(char *hd); + //! Serialize end-of-form token to GDL. + extern void end_form(void); + //! Serialize newline to GDL. + extern void newline_form(void); + //! Serialize space to GDL. + extern void space_form(void); + + //! Append string to GDL form. + extern void add_to_form(char *x); + //! Append string to GDL form without space delimiter. + extern void add_to_form_no_space(char *x); + //! Append char to GDL form. + extern void add_char_to_form(int x); + //! Append number to GDL form. + extern void add_num_to_form(int x); + //! Append number to GDL form without space delimiter. + extern void add_num_to_form_no_space(int x); + //! Append number or dice spec to GDL form. + /*! Write either a normal value or a dice spec, as appropriate. */ + extern void add_num_or_dice_to_form(int x, int valtype); + //! Append GDL form to GDL form. + extern void add_form_to_form(Obj *x); + + //! Serialize boolean-valued property to GDL. + extern void write_bool_prop( + char *name, + int value, + int dflt, + int nodefaulting, int addnewline); + //! Serialize integer-valued property to GDL. + extern void write_num_prop( + char *name, + int value, + int dflt, + int nodefaulting, int addnewline); + //! Serialize string-valued property to GDL. + extern void write_str_prop( + char *name, + char *value, + char *dflt, + int nodefaulting, int addnewline); + //! Serialize GDL Lisp-valued property to GDL. + extern void write_lisp_prop( + char *name, + struct a_obj *value, + struct a_obj *dflt, + int nodefaulting, int as_cdr, int addnewline); + #if (0) *************** *** 495,499 **** extern Obj *reverse(Obj *lis); extern Obj *find_at_key(Obj *lis, char *key); - extern Obj *replace_at_key(Obj *lis, char *key, Obj *newval); extern void dlisp(Obj *x); extern void print_form_and_value(FILE *fp, Obj *form); --- 578,581 ---- *************** *** 510,517 **** int maxdo, int maxval, int maxrslt, int *rslt); - - extern char *escaped_symbol(char *str); - extern char *escaped_string(char *str); - extern char *safe_escaped_string(char *str, int len); extern char *get_string(Obj *lis); --- 592,595 ---- Index: tables.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/tables.h,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** tables.h 28 May 2006 22:31:21 -0000 1.5 --- tables.h 2 Jun 2006 16:58:33 -0000 1.6 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald *************** *** 215,218 **** --- 215,240 ---- extern void interp_table(Obj *form); + #if (0) + //! Serialize stripe of table values to GDL. + extern void write_type_value_list( + int typ, int *flags, int dim, int (*getter)(int, int), int i); + #endif + + //! Serialize table to GDL. + /*! + Write out a single table. Only write it if it contains non-default + values, and try to find runs of constant value, since tables can be + really large, but often have constant areas within them. + */ + extern void write_table( + char *name, + int (*getter)(int, int), + int dflt, + int typ1, int typ2, int valtype, + int compress); + + //! Serialize tables to GDL. + extern void write_tables(int compress); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: types.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/types.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** types.h 29 May 2006 14:22:03 -0000 1.6 --- types.h 2 Jun 2006 16:58:33 -0000 1.7 *************** *** 8,12 **** Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 8,12 ---- Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2005-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 125,128 **** --- 125,145 ---- #define is_advance_type(a) ((a) >= 0 && (a) < numatypes) + //! Get wildcard symbol from game entity type. + #define star_from_typ(typ) \ + ((typ) == UTYP ? \ + "u*" : \ + ((typ) == MTYP ? \ + "m*" : \ + ((typ) == TTYP ? "t*" : "a*"))) + + //! Get name of type from game entity type and index. + #define name_from_typ(typ, i) \ + ((typ) == UTYP ? \ + shortest_escaped_name(i) : \ + ((typ) == MTYP ? \ + m_type_name(i) : \ + ((typ) == TTYP ? \ + t_type_name(i) : a_type_name(i)))) + //! Is terrain type cell-filling terrain? #define t_is_cell(t) (t_subtype(t) == cellsubtype) *************** *** 533,536 **** --- 550,559 ---- //! Get shortest distinct name for unit type. extern char *shortest_unique_name(int u); + //! Get shortest escaped name for unit type. + /*! + Return the shortest properly escaped name that can be used to identify + unit type. + */ + extern char *shortest_escaped_name(int u); //! Could given unit type be on given terrain type? *************** *** 722,725 **** --- 745,771 ---- extern void add_properties(Obj *form); + //! Serialize list of unit type-value pairs to GDL. + extern void write_utype_value_list( + char *name, short *arr, int dflt, int addnewline); + //! Serialize list of material type-value pairs to GDL. + extern void write_mtype_value_list( + char *name, short *arr, int dflt, int addnewline); + //! Serialize treasury list to GDL. + /*! Same as material type-value list but with wider values. */ + extern void write_treasury_list( + char *name, long *arr, int dflt, int addnewline); + //! Serialize list of advance type-value pairs to GDL. + extern void write_atype_value_list( + char *name, short *arr, int dflt, int addnewline); + + //! Serialize list of unit type-string pairs to GDL. + extern void write_utype_string_list( + char *name, char **arr, char *dflt, int addnewline); + + //! Serialize game entity type-name list to GDL. + extern void write_type_name_list(int typ, int *flags, int dim); + //! Serialize game entity types to GDL. + extern void write_types(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: history.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/history.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** history.h 23 May 2006 20:59:16 -0000 1.1 --- history.h 2 Jun 2006 16:58:33 -0000 1.2 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 129,132 **** --- 129,149 ---- extern HistEvent *history; + // Queries + + //! Find event type from GDL container. + extern int find_event_type(Obj *sym); + + //! Does pattern match event? + extern int pattern_matches_event(Obj *pattern, HistEvent *hevt); + + //! Describe event from GDL list. + extern void event_desc_from_list( + Side *side, Obj *lis, HistEvent *hevt, char *buf); + + // History Management + + //! Record event into game history. + extern HistEvent *record_event(HistEventType type, SideMask observers, ...); + // Lifecycle Management *************** *** 139,142 **** --- 156,164 ---- extern void interp_history(Obj *form); + //! Serialize historical event to GDL. + extern void write_historical_event(HistEvent *hevt); + //! Serialize history to GDL. + extern void write_history(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: gvars.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/gvars.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** gvars.h 23 May 2006 18:02:09 -0000 1.3 --- gvars.h 2 Jun 2006 16:58:33 -0000 1.4 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2005-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 187,190 **** --- 187,197 ---- extern void interp_variable(Obj *form, int isnew); + //! Serialize globals to GDL. + /*! + Write the globals. The "complete" flag forces all values out, even + if they match the compiled-in defaults. + */ + extern void write_globals(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: pact.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/pact.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pact.h 27 May 2006 23:01:41 -0000 1.1 --- pact.h 2 Jun 2006 16:58:33 -0000 1.2 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 42,47 **** --- 42,54 ---- #if (0) + //! Read agreement from GDL form. extern void interp_agreement(Obj *form); + + //! Serialize agreements to GDL. + extern void write_agreements(void); + //! Serialize agreement to GDL. + extern void write_agreement(struct a_agreement *agreement); + #endif Index: namer.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/namer.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** namer.h 27 May 2006 19:28:16 -0000 1.1 --- namer.h 2 Jun 2006 16:58:33 -0000 1.2 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2003-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 57,60 **** --- 57,63 ---- extern void interp_namer(Obj *form); + //! Serialize namer to GDL. + extern void write_namers(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END |
From: Eric M. <eri...@us...> - 2006-06-02 16:58:38
|
Update of /cvsroot/xconq/xconq/src/include/gdl/unit In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv23113/unit Modified Files: action.h goal.h pastunit.h plan.h task.h unit.h Log Message: Add CVS serialization support. Fix copyrights. Index: pastunit.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/unit/pastunit.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pastunit.h 29 May 2006 22:43:09 -0000 1.1 --- pastunit.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2006 Eric A. McDonald *************** *** 37,40 **** --- 37,41 ---- #include "gdl/lisp.h" + #include "gdl/side/side.h" NAMESPACE_XCONQ_BEGIN *************** *** 70,73 **** --- 71,87 ---- extern PastUnit *past_unit_list; + // Queries + + //! Get past unit from ID. + extern PastUnit *find_past_unit(int n); + + //! Return a handle for past unit on given side. + /*! + Build a short phrase describing a given past unit to a given side, + basically consisting of indication of unit's side, then of unit + itself. + */ + extern char *past_unit_handle(Side *side, PastUnit *past_unit); + // Lifecycle Management *************** *** 80,83 **** --- 94,100 ---- extern void interp_past_unit(Obj *form); + //! Serialize past unit to GDL. + extern void write_past_unit(PastUnit *pastunit); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: goal.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/unit/goal.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** goal.h 29 May 2006 22:43:09 -0000 1.1 --- goal.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 107,113 **** // GDL I/O ! //! Read goal from GDL form. extern Goal *interp_goal(Obj *form); NAMESPACE_GDL_END NAMESPACE_XCONQ_END --- 107,116 ---- // GDL I/O ! //! Read unit goal from GDL form. extern Goal *interp_goal(Obj *form); + //! Serialize unit goal to GDL. + extern void write_goal(Goal *goal, int keyword); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: unit.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/unit/unit.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** unit.h 29 May 2006 22:43:09 -0000 1.1 --- unit.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 68,71 **** --- 68,86 ---- #define unit_alt(unit) (((unit)->z & 1) == 0 ? ((unit)->z >> 1) : 0) + //! Unit's point value. + #define unit_point_value(unit) \ + ((unit)->extras ? (unit)->extras->point_value : -1) + + //! Turn unit is to appear on. + #define unit_appear_turn(unit) \ + ((unit)->extras ? (unit)->extras->appear : -1) + + //! Turn unit is to disappear on. + #define unit_disappear_turn(unit) \ + ((unit)->extras ? (unit)->extras->disappear : -1) + + //! Sides unit can be on. + #define unit_sides(unit) ((unit)->extras ? (unit)->extras->sides : lispnil) + //! Can unit pass the terrain at the cell? #define impassable(u, x, y) (!could_be_on((u)->type, terrain_at((x), (y)))) *************** *** 372,375 **** --- 387,405 ---- extern char *unit_desig(Unit *unit); + //! Handle briefly describing any unit. + /*! + This version allows the caller to supply a side other than the + unit's actual side, such as when describing an out-of-date image of + a unit that may have been captured. + */ + extern char *apparent_unit_handle(Side *side, Unit *unit, Side *side2); + //! Handle briefly describing side's unit. + /*! + Build a short phrase describing a given unit to a given side, + basically consisting of indication of unit's side, then of unit + itself. + */ + extern char *unit_handle(Side *side, Unit *unit); + //! Find alive unit by ID. /*! \todo This is used a lot, it should be sped up. */ *************** *** 402,405 **** --- 432,447 ---- extern int can_occupy(Unit *unit, Unit *transport); + // Sorting + + //! Sort units. + /*! Do a bubble sort. + Data is generally coherent, so bubble sort not too bad if we allow + early termination when everything is already in order. + + \note If slowness objectionable, replace with something clever, but be + sure that average performance in real games is what's being improved. + */ + extern void sort_units(int byidonly); + // Vision and Visibility *************** *** 452,455 **** --- 494,508 ---- extern void init_unit_opinions(Unit *unit, int nsides); + //! Get rid of all dead units at once. + /*! + This routine is basically a garbage collector, and should not be + called during a unit list traversal. The process starts by finding + the first live unit, making it the head, then linking around all in + the middle. Dead units stay on the dead unit list for each side + until that side has had a chance to move. Then they are finally + flushed in a permanent fashion. + */ + extern void flush_dead_units(void); + // Images *************** *** 485,488 **** --- 538,551 ---- extern Unit *interp_unit(Obj *form); + //! Serialize unit properties to GDL. + /*! Write various properties, but only if they have non-default values. */ + extern void write_unit_properties(Unit *unit); + //! Serialize units to GDL. + /*! + \todo Should write out "unit groups" with dict prepended, then can use with + multiple games + */ + extern void write_units(struct a_module *module); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: plan.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/unit/plan.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** plan.h 29 May 2006 22:43:09 -0000 1.1 --- plan.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 41,44 **** --- 41,49 ---- #include "gdl/unit/goal.h" + // Iterator Macros + + #define for_all_tasks(plan,task) \ + for (task = (plan)->tasks; task != NULL; task = task->next) + NAMESPACE_XCONQ_BEGIN NAMESPACE_GDL_BEGIN *************** *** 115,118 **** --- 120,128 ---- } Plan; + // Global Variables + + //! Array of plan type names. + extern char *plantypenames[]; + // Lifecycle Management *************** *** 135,141 **** // GDL I/O ! // Read unit plan from GDL form. extern void interp_unit_plan(struct a_unit *unit, Obj *props); NAMESPACE_GDL_END NAMESPACE_XCONQ_END --- 145,154 ---- // GDL I/O ! //! Read unit plan from GDL form. extern void interp_unit_plan(struct a_unit *unit, Obj *props); + //! Serialize unit plan to GDL. + extern void write_unit_plan(Unit *unit); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: action.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/unit/action.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** action.h 29 May 2006 22:43:09 -0000 1.1 --- action.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 132,135 **** --- 132,140 ---- extern void interp_action(Action *action, Obj *props); + //! Serialize action to GDL. + extern void write_action(Action *action, int id); + //! Serialize unit actor state to GDL. + extern void write_unit_act(Unit *unit); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: task.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/unit/task.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** task.h 29 May 2006 22:43:09 -0000 1.1 --- task.h 2 Jun 2006 16:58:34 -0000 1.2 *************** *** 44,47 **** --- 44,52 ---- #define MAXTASKARGS 6 + // Function Macros: Queries + + //! Is argument a task type? + #define is_task_type(x) (between(0, (x), NUMTASKTYPES - 1)) + NAMESPACE_XCONQ_BEGIN NAMESPACE_GDL_BEGIN *************** *** 158,161 **** --- 163,169 ---- extern Task *interp_task(Obj *form); + //! Serialize task to GDL. + extern void write_task(Task *task); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END |
From: Eric M. <eri...@us...> - 2006-06-02 16:58:37
|
Update of /cvsroot/xconq/xconq/src/include/gdl/media In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv23113/media Modified Files: imf.h img.h Log Message: Add CVS serialization support. Fix copyrights. Index: imf.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/media/imf.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** imf.h 30 May 2006 02:49:03 -0000 1.2 --- imf.h 2 Jun 2006 16:58:34 -0000 1.3 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald *************** *** 90,94 **** } ImageFamily; ! // Global Variables: Image Families //! Array of all image families loaded. --- 90,94 ---- } ImageFamily; ! // Global Variables //! Array of all image families loaded. *************** *** 97,100 **** --- 97,105 ---- extern int numimages; + //! All GDL image families on record. + extern ImageFamily **recorded_imfs; + //! Number of GDL image families on record. + extern int num_recorded_imfs; + // Queries *************** *** 116,119 **** --- 121,135 ---- // GDL I/O + //! Lookup color name from its RGB triplet. + /*! + Given rgb components, return names of standard colors if the match + is close. + */ + extern char *find_color_name(int r, int g, int b); + + //! Read palette color from GDL palette entry. + extern void parse_lisp_palette_entry( + Obj *palentry, int *c, int *r, int *g, int *b); + //! Read GDL form into GDL image family. /*! *************** *** 126,129 **** --- 142,150 ---- extern ImageFamily *interp_imf(Obj *form); + //! Serialize GDL image family to GDL. + extern void write_imf(FILE *fp, ImageFamily *imf); + //! Serialize images to GDL. + extern void write_images(void); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: img.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/media/img.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** img.h 30 May 2006 02:49:03 -0000 1.2 --- img.h 2 Jun 2006 16:58:34 -0000 1.3 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald |
From: Eric M. <eri...@us...> - 2006-06-02 16:57:52
|
Update of /cvsroot/xconq/xconq/src/gdl/side In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv22145/side Modified Files: cellview.cc doctrine.cc side.cc sidemask.cc sorder.cc Log Message: Add GDL serialization support. Fix copyrights. Fix automakefile. Index: sidemask.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/side/sidemask.cc,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** sidemask.cc 30 May 2006 02:34:13 -0000 1.2 --- sidemask.cc 2 Jun 2006 16:57:43 -0000 1.3 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2006 Eric A. McDonald Index: side.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/side/side.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** side.cc 30 May 2006 02:34:13 -0000 1.1 --- side.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 40,47 **** --- 40,50 ---- #include "gdl/dir.h" #include "gdl/namer.h" + #include "gdl/player.h" #include "gdl/side/side.h" #include "gdl/history.h" + #include "gdl/score.h" #include "gdl/gamearea/area.h" #include "gdl/world.h" + #include "gdl/module.h" // Function Macros: Queries *************** *** 60,63 **** --- 63,68 ---- int numtotsides; + AI_ops *all_ai_ops; + // Global Variables: Uniques *************** *** 72,77 **** --- 77,88 ---- int nextsideid; + // Global Variables: Behavior Options + + //! To compress layer output or not to compress layer output? + int tmpcompress; + // Global Variables: Buffers + //! Scratch side. Side *tmpside; *************** *** 2246,2249 **** --- 2257,2624 ---- } + void + ai_save_state(Side *side) + { + Obj *(*fn)(Side *side), *state = lispnil; + + fn = all_ai_ops[side->aitype].to_save_state; + if (fn) + state = (*fn)(side); + /* Don't bother if there's no AI state to mess with. */ + if (side->aidata == lispnil && state == lispnil) + return; + side->aidata = + replace_at_key(side->aidata, side->player->aitypename, state); + } + + void + write_side_view(Side *side, int compress) + { + int t, m, x, y; + UnitView *uview; + + tmpside = side; + tmpcompress = compress; + if (side->terrview) + write_one_side_view_layer(K_TERRAIN_VIEW, fn_terrain_view); + if (!g_see_terrain_always()) { + if (side->terrview) + write_one_side_view_layer(K_TERRAIN_VIEW_DATES, + fn_terrain_view_date); + if (numcelltypes < numttypes) { + for_all_terrain_types(t) { + if (!t_is_cell(t)) { + tmpttype = t; + if (side->auxterrview[t]) + write_one_side_view_layer(K_AUX_TERRAIN_VIEW, + fn_aux_terrain_view); + /* Caused crashes since the code that allocates this layer in init_view + is currently commented out. */ + #if 0 + if (side->auxterrviewdate[t]) + write_one_side_view_layer(K_AUX_TERRAIN_VIEW_DATES, + fn_aux_terrain_view_date); + #endif + } + } + } + } + if (side->materialview) { + for_all_material_types(m) { + if (1) { + tmpmtype = m; + if (side->materialview[m]) + write_one_side_view_layer(K_MATERIAL_VIEW, fn_material_view); + if (side->materialviewdate[m]) + write_one_side_view_layer(K_MATERIAL_VIEW_DATES, + fn_material_view_date); + } + } + } + /* Write out unit view objects. */ + if (!side->see_all && side->unit_views != NULL) { + newline_form(); + start_form(key(K_SIDE)); + add_num_to_form(side->id); + space_form(); + start_form(key(K_UNIT_VIEWS)); + newline_form(); + for_all_cells(x, y) { + for_all_view_stack_with_occs(side, x, y, uview) { + /* (should filter out side's own units?) */ + space_form(); + space_form(); + start_form(shortest_escaped_name(uview->type)); + add_num_to_form(uview->siden); + add_to_form(uview->name); + add_num_to_form(uview->size); + add_num_to_form(uview->x); + add_num_to_form(uview->y); + add_num_to_form(uview->complete); + add_num_to_form(uview->date); + add_num_to_form(uview->id); + add_to_form(uview->image_name); + end_form(); + newline_form(); + } + } + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + if (!g_see_weather_always()) { + if (side->tempview) { + write_one_side_view_layer(K_TEMPERATURE_VIEW, fn_temp_view); + write_one_side_view_layer(K_TEMPERATURE_VIEW_DATES, + fn_temp_view_date); + } + if (side->cloudview) { + write_one_side_view_layer(K_CLOUD_VIEW, fn_cloud_view); + write_one_side_view_layer(K_CLOUD_BOTTOM_VIEW, + fn_cloud_bottom_view); + write_one_side_view_layer(K_CLOUD_HEIGHT_VIEW, + fn_cloud_height_view); + write_one_side_view_layer(K_CLOUD_VIEW_DATES, fn_cloud_view_date); + } + if (side->windview) { + write_one_side_view_layer(K_WIND_VIEW, fn_wind_view); + write_one_side_view_layer(K_WIND_VIEW_DATES, fn_wind_view_date); + } + } + } + + void + write_side_properties(Side *side) + { + int i, u, u2, anyudoctrines; + + write_str_prop(key(K_NAME), side->name, "", FALSE, TRUE); + write_str_prop(key(K_LONG_NAME), side->longname, "", FALSE, TRUE); + write_str_prop(key(K_SHORT_NAME), side->shortname, "", FALSE, TRUE); + write_str_prop(key(K_NOUN), side->noun, "", FALSE, TRUE); + write_str_prop(key(K_PLURAL_NOUN), side->pluralnoun, "", FALSE, TRUE); + write_str_prop(key(K_ADJECTIVE), side->adjective, "", FALSE, TRUE); + write_str_prop(key(K_COLOR), side->colorscheme, "", FALSE, TRUE); + write_str_prop(key(K_EMBLEM_NAME), side->emblemname, "", FALSE, TRUE); + write_utype_string_list(key(K_UNIT_NAMERS), side->unitnamers, "", TRUE); + write_lisp_prop( + key(K_UNITS), side->possible_units, lispnil, FALSE, FALSE, TRUE); + write_str_prop(key(K_CLASS), side->sideclass, "", FALSE, TRUE); + write_bool_prop(key(K_ACTIVE), side->ingame, 1, FALSE, TRUE); + /* side->everingame is only interesting if it differs from ingame, + so use the value of ingame as the default. */ + write_bool_prop(key(K_EVER_ACTIVE), side->everingame, side->ingame, + FALSE, TRUE); + write_num_prop(key(K_PRIORITY), side->priority, -1, FALSE, TRUE); + write_num_prop(key(K_STATUS), side->status, 0, FALSE, TRUE); + if (!debugging_state_sync) + write_num_prop(key(K_TURN_TIME_USED), side->turntimeused, 0, FALSE, TRUE); + if (!debugging_state_sync) + write_num_prop( + key(K_TOTAL_TIME_USED), side->totaltimeused, 0, FALSE, TRUE); + write_num_prop(key(K_TIMEOUTS), side->timeouts, 0, FALSE, TRUE); + write_num_prop(key(K_TIMEOUTS_USED), side->timeoutsused, 0, FALSE, TRUE); + write_num_prop(key(K_FINISHED_TURN), side->finishedturn, 0, FALSE, TRUE); + write_num_prop(key(K_WILLING_TO_DRAW), side->willingtodraw, 0, FALSE, TRUE); + write_num_prop(key(K_ADVANTAGE), side->advantage, 1, FALSE, TRUE); + write_num_prop(key(K_ADVANTAGE_MIN), side->minadvantage, 1, FALSE, TRUE); + write_num_prop(key(K_ADVANTAGE_MAX), side->maxadvantage, 1, FALSE, TRUE); + write_num_prop( + key(K_CONTROLLED_BY), + (side->controlled_by ? side_number(side->controlled_by) : -1), + -1, FALSE, TRUE); + write_num_prop( + key(K_SELF_UNIT), + (side->self_unit ? side->self_unit->id : 0), 0, FALSE, TRUE); + write_num_prop( + key(K_PLAYER), (side->player ? side->player->id : -1), -1, FALSE, TRUE); + write_num_prop(key(K_DEFAULT_DOCTRINE), + (side->default_doctrine ? side->default_doctrine->id : 0), + 0, FALSE, TRUE); + write_num_prop(key(K_CURRENT_ADVANCE), side->research_topic, NOADVANCE, + FALSE, TRUE); + write_num_prop(key(K_ADVANCE_GOAL), side->research_goal, NONATYPE, FALSE, + TRUE); + write_atype_value_list(key(K_ADVANCES_DONE), side->advance, 0, TRUE); + write_treasury_list(key(K_TREASURY), side->treasury, 0, TRUE); + anyudoctrines = FALSE; + if (side->udoctrine != NULL) { + for_all_unit_types(u) { + if (side->udoctrine[u] != side->default_doctrine) { + anyudoctrines = TRUE; + break; + } + } + } + if (anyudoctrines) { + space_form(); + start_form(key(K_DOCTRINES)); + for_all_unit_types(u) { + if (side->udoctrine[u] != side->default_doctrine) { + space_form(); + start_form(shortest_escaped_name(u)); + if (side->udoctrine[u]->name) + add_to_form(escaped_symbol(side->udoctrine[u]->name)); + else + add_num_to_form(side->udoctrine[u]->id); + end_form(); + } + } + end_form(); + newline_form(); + space_form(); + } + write_side_value_list(key(K_TRUSTS), side->trusts, FALSE, TRUE); + write_side_value_list(key(K_TRADES), side->trades, FALSE, TRUE); + write_utype_value_list(key(K_START_WITH), side->startwith, 0, TRUE); + write_utype_value_list(key(K_NEXT_NUMBERS), side->counts, 0, TRUE); + write_utype_value_list(key(K_TECH), side->tech, 0, TRUE); + write_utype_value_list(key(K_INIT_TECH), side->inittech, 0, TRUE); + write_utype_value_list(key(K_ALREADY_SEEN), side->already_seen, -1, TRUE); + write_utype_value_list( + key(K_ALREADY_SEEN_INDEPENDENT), side->already_seen_indep, -1, TRUE); + write_standing_orders(side); + if (side->scores) { + space_form(); + start_form(key(K_SCORES)); + for (i = 0; i < numscores; ++i) { + add_num_to_form(side->scores[i]); + } + end_form(); + newline_form(); + space_form(); + } + write_lisp_prop(key(K_INSTRUCTIONS), side->instructions, + lispnil, FALSE, FALSE, TRUE); + /* Write out statistics. */ + if (side->gaincounts != NULL) { + space_form(); + start_form(key(K_GAIN_COUNTS)); + for (i = 0; i < numutypes * num_gain_reasons; ++i) { + add_num_to_form(side->gaincounts[i]); + } + end_form(); + newline_form(); + space_form(); + } + if (side->losscounts != NULL) { + space_form(); + start_form(key(K_LOSS_COUNTS)); + for (i = 0; i < numutypes * num_loss_reasons; ++i) { + add_num_to_form(side->losscounts[i]); + } + end_form(); + newline_form(); + space_form(); + } + if (side->atkstats != NULL) { + space_form(); + start_form(key(K_ATTACK_STATS)); + for_all_unit_types(u) { + if (side->atkstats[u] != NULL) { + newline_form(); + space_form(); + space_form(); + space_form(); + start_form(shortest_escaped_name(u)); + for_all_unit_types(u2) { + add_num_to_form(side_atkstats(side, u, u2)); + } + end_form(); + } + } + end_form(); + newline_form(); + space_form(); + } + if (side->hitstats != NULL) { + space_form(); + start_form(key(K_HIT_STATS)); + for_all_unit_types(u) { + if (side->hitstats[u] != NULL) { + newline_form(); + space_form(); + space_form(); + space_form(); + start_form(shortest_escaped_name(u)); + for_all_unit_types(u2) { + add_num_to_form(side_hitstats(side, u, u2)); + } + end_form(); + } + } + end_form(); + newline_form(); + space_form(); + } + if (side->could_act_with) + write_utype_value_list( + key(K_COULD_ACT_WITH), side->could_act_with, FALSE, TRUE); + if (side->could_construct) + write_utype_value_list( + key(K_COULD_CONSTRUCT), side->could_construct, FALSE, TRUE); + if (side->could_develop) + write_utype_value_list( + key(K_COULD_DEVELOP), side->could_develop, FALSE, TRUE); + if (side->could_research) + write_atype_value_list( + key(K_COULD_RESEARCH), side->could_research, FALSE, TRUE); + /* Have the AI paste its useful state into distinct element of + side->aidata. */ + if (side_has_local_ai(side)) { + ai_save_state(side); + } + write_lisp_prop(key(K_AI_DATA), side->aidata, lispnil, FALSE, TRUE, TRUE); + write_lisp_prop(key(K_UI_DATA), side->uidata, lispnil, FALSE, TRUE, TRUE); + } + + void + write_sides(Module *module) + { + Side *side; + + newline_form(); + add_to_form(";"); + add_num_to_form(numtotsides); + add_to_form("sides including the independent 0 side."); + newline_form(); + Dprintf("Will try to write %d sides ...\n", numtotsides); + for_all_real_sides(side) { + start_form(key(K_SIDE)); + add_num_to_form(side->id); + if (symbolp(side->symbol)) + add_to_form(escaped_symbol(c_string(side->symbol))); + newline_form(); + space_form(); + write_side_properties(side); + space_form(); + end_form(); + newline_form(); + if (module->def_all || module->def_side_views) + write_side_view(side, module->compress_layers); + Dprintf(" Wrote side %s\n", side_desig(side)); + } + /* Even though the indepside is another side, the properties of + independent units are a separate type of form. */ + start_form(key(K_INDEPENDENT_UNITS)); + newline_form(); + write_side_properties(indepside); + space_form(); + end_form(); + newline_form(); + Dprintf(" Wrote independent unit properties\n"); + Dprintf("... Done writing sides\n"); + } + + void + write_side_value_list(char *name, short *arr, int dflt, int addnewline) + { + int s, writeany; + + if (arr == NULL) + return; + writeany = FALSE; + for (s = 0; s <= numsides; ++s) { + if (arr[s] != dflt) { + writeany = TRUE; + break; + } + } + if (!writeany) + return; + space_form(); + start_form(name); + for (s = 0; s <= numsides; ++s) { + add_num_to_form(arr[s]); + } + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: cellview.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/side/cellview.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** cellview.cc 30 May 2006 02:34:13 -0000 1.1 --- cellview.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 49,52 **** --- 49,136 ---- // Game Area View Layer Accessors + int + fn_terrain_view(int x, int y) + { + return terrain_view(tmpside, x, y); + } + + int + fn_terrain_view_date(int x, int y) + { + return terrain_view_date(tmpside, x, y); + } + + int + fn_aux_terrain_view(int x, int y) + { + return aux_terrain_view(tmpside, x, y, tmpttype); + } + + int + fn_aux_terrain_view_date(int x, int y) + { + return aux_terrain_view_date(tmpside, x, y, tmpttype); + } + + int + fn_material_view(int x, int y) + { + return material_view(tmpside, x, y, tmpmtype); + } + + int + fn_material_view_date(int x, int y) + { + return material_view_date(tmpside, x, y, tmpmtype); + } + + int + fn_temp_view(int x, int y) + { + return temperature_view(tmpside, x, y); + } + + int + fn_temp_view_date(int x, int y) + { + return temperature_view_date(tmpside, x, y); + } + + int + fn_cloud_view(int x, int y) + { + return cloud_view(tmpside, x, y); + } + + int + fn_cloud_bottom_view(int x, int y) + { + return cloud_bottom_view(tmpside, x, y); + } + + int + fn_cloud_height_view(int x, int y) + { + return cloud_height_view(tmpside, x, y); + } + + int + fn_cloud_view_date(int x, int y) + { + return cloud_view_date(tmpside, x, y); + } + + int + fn_wind_view(int x, int y) + { + return wind_view(tmpside, x, y); + } + + int + fn_wind_view_date(int x, int y) + { + return wind_view_date(tmpside, x, y); + } + void fn_set_terrain_view(int x, int y, int val) *************** *** 331,334 **** --- 415,435 ---- } + void + write_one_side_view_layer(int propkey, int (*fn)(int x, int y)) + { + newline_form(); + start_form(key(K_SIDE)); + add_num_to_form(tmpside->id); + space_form(); + start_form(key((enum keywords)propkey)); + newline_form(); + write_rle(fn, -32767, 32767, NULL, tmpcompress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: doctrine.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/side/doctrine.cc,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** doctrine.cc 30 May 2006 02:34:13 -0000 1.2 --- doctrine.cc 2 Jun 2006 16:57:43 -0000 1.3 *************** *** 243,246 **** --- 243,276 ---- } + void + write_doctrines(void) + { + Doctrine *doc; + + for_all_doctrines(doc) { + /* (should filter out doctrines with no non-default values) */ + start_form(key(K_DOCTRINE)); + if (doc->name) + add_to_form(escaped_symbol(doc->name)); + else + add_num_to_form(doc->id); + newline_form(); + space_form(); + write_num_prop(key(K_RESUPPLY_PERCENT), doc->resupply_percent, + /* (should get these defaults from a common place) */ + 50, FALSE, TRUE); + write_num_prop(key(K_REARM_PERCENT), doc->rearm_percent, + 20, FALSE, TRUE); + write_num_prop(key(K_REPAIR_PERCENT), doc->repair_percent, + 35, FALSE, TRUE); + write_utype_value_list(key(K_CONSTRUCTION_RUN), doc->construction_run, + 0, TRUE); + write_num_prop(key(K_LOCKED), doc->locked, 0, FALSE, TRUE); + space_form(); + end_form(); + newline_form(); + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: sorder.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/side/sorder.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** sorder.cc 30 May 2006 02:34:13 -0000 1.1 --- sorder.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 228,231 **** --- 228,298 ---- } + void + write_standing_orders(Side *side) + { + int u, u1, numtypes, numargs; + char *str = NULL; + StandingOrder *sorder; + + for (sorder = side->orders; sorder != NULL; sorder = sorder->next) { + space_form(); + start_form(key(K_STANDING_ORDER)); + /* (should break into a write_utype_list) */ + numtypes = u1 = 0; + for_all_unit_types(u) { + if (sorder->types[u]) { + ++numtypes; + u1 = u; + } + } + if (numtypes == 1) { + add_to_form(shortest_escaped_name(u1)); + } else if (numtypes == numutypes) { + add_to_form(key(K_USTAR)); + } else { + space_form(); + start_form(""); + for_all_unit_types(u) + add_num_to_form(sorder->types[u]); + end_form(); + } + space_form(); + switch (sorder->condtype) { + case sorder_always: + str = key(K_ALWAYS); + numargs = 0; + break; + case sorder_at: + str = key(K_AT); + numargs = 2; + break; + case sorder_in: + str = key(K_IN); + numargs = 1; + break; + case sorder_near: + str = key(K_NEAR); + numargs = 3; + break; + default: + case_panic("standing order condition type", sorder->condtype); + break; + } + start_form(str); + if (numargs > 0) + add_num_to_form(sorder->a1); + if (numargs > 1) + add_num_to_form(sorder->a2); + if (numargs > 2) + add_num_to_form(sorder->a3); + end_form(); + space_form(); + write_task(sorder->task); + end_form(); + newline_form(); + space_form(); + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END |
From: Eric M. <eri...@us...> - 2006-06-02 16:57:48
|
Update of /cvsroot/xconq/xconq/src/gdl/unit In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv22145/unit Modified Files: action.cc goal.cc pastunit.cc plan.cc task.cc unit.cc unitview.cc Log Message: Add GDL serialization support. Fix copyrights. Fix automakefile. Index: unitview.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/unit/unitview.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** unitview.cc 29 May 2006 22:43:09 -0000 1.1 --- unitview.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 8,12 **** Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 8,12 ---- Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2005-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// Index: unit.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/unit/unit.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** unit.cc 29 May 2006 22:43:09 -0000 1.1 --- unit.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 42,45 **** --- 42,46 ---- #include "gdl/gamearea/area.h" #include "gdl/world.h" + #include "gdl/module.h" NAMESPACE_XCONQ_BEGIN *************** *** 140,143 **** --- 141,148 ---- static Obj *find_unit_spec_by_number(int num); + // Local Function Declarations: Sorting + + static int compare_units(Unit *unit1, Unit *unit2); + // Local Function Declarations: Position Manipulation *************** *** 163,166 **** --- 168,178 ---- static void delete_unit(Unit *unit); + //! Flush dead unit. + /*! + Keep it clean - hit all links to other places. Some might not be + strictly necessary, but this is not an area to take chances with. + */ + static void flush_one_unit(Unit *unit); + // Queries *************** *** 283,286 **** --- 295,435 ---- } + char * + apparent_unit_handle(Side *side, Unit *unit, Side *side2) + { + char *utypename, *fmtstr, smallbuf[40], sidebuf[100]; + Side *side3; + Obj *frest, *fmt1; + + /* This should be impossible, be really obvious if it happens. */ + if (side2 == NULL) + return "null side2 in apparent_unit_handle?"; + /* Make sure our working space exists. */ + if (unitbuf == NULL) + unitbuf = (char *)xmalloc(BUFSIZE); + /* Handle various weird situations. */ + if (unit == NULL) + return "???"; + if (!alive(unit)) { + sprintf(unitbuf, "dead #%d", unit->id); + return unitbuf; + } + unitbuf[0] = '\0'; + /* Decide how to identify the side. If the unit's original side + is not its current side, list both of them. */ + side3 = NULL; + if (unit->origside != NULL && side2 != unit->origside) + side3 = unit->origside; + sidebuf[0] = '\0'; + if (side2 == side) { + strcat(sidebuf, "your"); + } else { + /* If the side adjective is a genitive (ends in 's, s' or z') + we should skip the definite article. */ + int len = strlen(side_adjective(side2)); + char *end = side_adjective(side2) + len - 2; + + if (strcmp(end, "'s") != 0 + && strcmp(end, "s'") != 0 + && strcmp(end, "z'") != 0) + strcat(sidebuf, "the "); + strcat(sidebuf, side_adjective(side2)); + } + + /* Generates a lot of extra text of limited interest to the player. */ + #if 0 + if (side3 != NULL) { + if (side3 == side) { + strcat(sidebuf, " (formerly your)"); + } else if (side3 == indepside) { + /* Don't add anything for captured independents. While + technically there's no reason not to do this, in + practice a side will often have many captured indeps, + and this keeps the text from getting too cluttered. */ + } else { + strcat(sidebuf, " (formerly "); + strcat(sidebuf, side_adjective(side3)); + strcat(sidebuf, ")"); + } + } + #endif + + /* Now add the unit's unique description. */ + utypename = u_type_name(unit->type); + /* If we have special formatting info, interpret it. */ + if (u_desc_format(unit->type) != lispnil) { + for_all_list(u_desc_format(unit->type), frest) { + fmt1 = car(frest); + if (stringp(fmt1)) { + /* Append strings verbatim. */ + strcat(unitbuf, c_string(fmt1)); + } else if (symbolp(fmt1)) { + /* Symbols indicate the types of data to format and + output. */ + fmtstr = c_string(fmt1); + if (strcmp(fmtstr, "name") == 0) { + strcat(unitbuf, (unit->name ? unit->name : "anon")); + } else if (strcmp(fmtstr, "position") == 0) { + sprintf(smallbuf, "%d,%d", unit->x, unit->y); + strcat(unitbuf, smallbuf); + } else if (strcmp(fmtstr, "side") == 0) { + strcat(unitbuf, sidebuf); + } else if (strcmp(fmtstr, "type") == 0) { + strcat(unitbuf, utypename); + } else if (strcmp(fmtstr, "side-name") == 0) { + strcat(unitbuf, side_name(unit->side)); + } else if (strcmp(fmtstr, "side-adjective") == 0) { + strcat(unitbuf, side_adjective(unit->side)); + } else { + strcat(unitbuf, "??description-format??"); + } + } else { + strcat(unitbuf, "??description-format??"); + } + } + return unitbuf; + } else { + strcat(unitbuf, sidebuf); + strcat(unitbuf, " "); + } + /* If this unit is a self unit, say so. */ + if (unit->side != NULL && unit == unit->side->self_unit) { + if (!mobile(unit->type) || u_advanced(unit->type)) { + strcat(unitbuf, "capital "); + } else { + strcat(unitbuf, "leader "); + } + if (unit->name) { + tprintf(unitbuf, "%s", unit->name); + } else if (unit->number > 0) { + tprintf(unitbuf, "%d%s %s", + unit->number, ordinal_suffix(unit->number), utypename); + } else { + strcat(unitbuf, utypename); + } + /* Default formats for units. */ + } else { + if (unit->name) { + tprintf(unitbuf, "%s %s", utypename, unit->name); + } else if (unit->number > 0) { + tprintf(unitbuf, "%d%s %s", + unit->number, ordinal_suffix(unit->number), utypename); + } else { + strcat(unitbuf, utypename); + } + } + return unitbuf; + } + + char * + unit_handle(Side *side, Unit *unit) + { + Side *side2 = NULL; + + if (unit != NULL) + side2 = unit->side; + return apparent_unit_handle(side, unit, side2); + } + static Obj * *************** *** 549,552 **** --- 698,755 ---- } + // Sorting + + static + int + compare_units(Unit *unit1, Unit *unit2) + { + if (unit1->type != unit2->type) + return (unit1->type - unit2->type); + if (unit1->name && unit2->name == NULL) + return -1; + if (unit1->name == NULL && unit2->name) + return 1; + if (unit1->name && unit2->name) + return strcmp(unit1->name, unit2->name); + if (unit1->number != unit2->number) + return (unit1->number - unit2->number); + /* Ids impose a total ordering. */ + return (unit1->id - unit2->id); + } + + void + sort_units(int byidonly) + { + int flips; + int passes = 0; + register Unit *unit, *nextunit; + Side *side; + + for_all_sides(side) { + passes = 0; + flips = TRUE; + while (flips) { + flips = FALSE; + for_all_side_units(side, unit) { + if (unit->next != side->unithead + && (byidonly ? ((unit->id - unit->next->id) > 0) + : (compare_units(unit, unit->next) > 0))) { + flips = TRUE; + /* Reorder the units by fiddling with their links. */ + nextunit = unit->next; + unit->prev->next = nextunit; + nextunit->next->prev = unit; + nextunit->prev = unit->prev; + unit->next = nextunit->next; + nextunit->next = unit; + unit->prev = nextunit; + } + ++passes; + } + } + } + Dprintf("Sorting passes = %d\n", passes); + } + // Vision and Visibility *************** *** 919,922 **** --- 1122,1176 ---- } + static + void + flush_one_unit(Unit *unit) + { + unit->id = -1; + unit->imf = NULL; + unit->image_name = NULL; + unit->occupant = NULL; + unit->transport = NULL; + unit->nexthere = NULL; + unit->prev = NULL; + unit->unext = NULL; + /* Add it on the front of the list of available units. */ + unit->next = freeunits; + freeunits = unit; + } + + void + flush_dead_units(void) + { + Unit *unit, *prevunit, *nextunit; + + if (unitlist == NULL) + return; + unit = unitlist; + while (!alive(unit)) { + nextunit = unit->unext; + delete_unit(unit); + flush_one_unit(unit); + unit = nextunit; + if (unit == NULL) + break; + } + unitlist = unit; + /* Since the first unit of unitlist is guaranteed live now, + we know that prevunit will always be set correctly; + but mollify insufficiently intelligent compilers. */ + prevunit = NULL; + for_all_units(unit) { + if (!alive(unit)) { + nextunit = unit->unext; + prevunit->unext = unit->unext; + delete_unit(unit); + flush_one_unit(unit); + unit = prevunit; + } else { + prevunit = unit; + } + } + } + // Images *************** *** 1459,1462 **** --- 1713,1861 ---- } + void + write_unit_properties(Unit *unit) + { + write_str_prop(key(K_IMAGE_NAME), unit->image_name, NULL, FALSE, FALSE); + write_num_prop(key(K_NB), unit->number, 0, FALSE, FALSE); + write_num_prop(key(K_HP), unit->hp, u_hp(unit->type), FALSE, FALSE); + write_num_prop(key(K_CP), unit->cp, u_cp(unit->type), FALSE, FALSE); + write_num_prop(key(K_CXP), unit->cxp, 0, FALSE, FALSE); + write_num_prop(key(K_MO), unit->morale, 0, FALSE, FALSE); + write_num_prop(key(K_TRK), unit->tracking, NOSIDES, FALSE, FALSE); + write_utype_value_list(key(K_TP), unit->tooling, 0, FALSE); + write_side_value_list(key(K_OPINIONS), unit->opinions, 0, FALSE); + /* Getting the defaults right for the supply list requires more + cleverness, alway write for now. */ + write_treasury_list(key(K_M), unit->supply, -1, FALSE); + write_num_prop(key(K_POINT_VALUE), unit_point_value(unit), -1, FALSE, + FALSE); + write_num_prop(key(K_APPEAR), unit_appear_turn(unit), -1, FALSE, FALSE); + /* (should do appear x,y also here?) */ + write_num_prop(key(K_DISAPPEAR), unit_disappear_turn(unit), -1, FALSE, + FALSE); + write_lisp_prop(key(K_SIDES), unit_sides(unit), lispnil, FALSE, TRUE, + FALSE); + /* Advanced unit support. */ + if (!u_advanced(unit->type)) + return; + write_num_prop(key(K_SIZE), unit->size, 0, FALSE, FALSE); + write_num_prop(key(K_REACH), unit->reach, 0, FALSE, FALSE); + write_num_prop(key(K_USEDCELLS), unit->usedcells, 0, FALSE, FALSE); + write_num_prop(key(K_MAXCELLS), unit->maxcells, 1, FALSE, FALSE); + write_num_prop(key(K_CURADVANCE), unit->curadvance, -1, FALSE, FALSE); + write_num_prop(key(K_POPULATION), unit->population, 1, FALSE, FALSE); + write_mtype_value_list(key(K_PRODUCTION), unit->production, 0, FALSE); + write_num_prop(key(K_CP_STASH), unit->cp_stash, FALSE, FALSE, FALSE); + write_num_prop(key(K_CREATION_ID), unit->creation_id, 0, FALSE, FALSE); + } + + void + write_units(Module *module) + { + int x0, y0, x, y, numtowrite; + Unit *unit; + Side *loopside; + + /* Make sure no dead units get saved. */ + flush_dead_units(); + /* Make a consistent ordering. */ + sort_units(module->def_all || module->def_unit_ids); + numtowrite = 0; + for_all_sides(loopside) { + for_all_side_units(loopside, unit) { + if (alive(unit)) + ++numtowrite; + } + } + add_to_form(";"); + add_num_to_form(numtowrite); + add_to_form(" units"); + newline_form(); + /* Need to write out the defaults being assumed subsequently. */ + /* maybe use those in postprocessing. */ + start_form(key(K_UNIT_DEFAULTS)); + end_form(); + newline_form(); + Dprintf("Writing %d units ...\n", numliveunits); + for_all_sides(loopside) { + for_all_side_units(loopside, unit) { + if (alive(unit)) { + /* K_AT always written */ + /* K_S always written */ + /* If the unit will appear later, must write out that + later position, possibly mapped to a new place if + the map is being reshaped. */ + if (unit->cp < 0 && unit_appear_turn(unit) >= 0) { + x0 = (- unit->prevx); y0 = (- unit->prevy); + } else { + x0 = unit->x; y0 = unit->y; + } + if (doreshape) { + reshaped_point(x0, y0, &x, &y); + } else { + x = x0; y = y0; + } + /* If these were negative values made positive for the + purposes of reshaping, make them negative again. */ + if (unit->cp < 0 && unit_appear_turn(unit) >= 0) { + x = (- x); y = (- y); + } + start_form(shortest_escaped_name(unit->type)); + add_num_to_form(x); + add_num_to_form(y); + if (unit->side != NULL && unit->side->symbol != lispnil) + add_to_form(escaped_symbol(c_string(unit->side->symbol))); + else + add_num_to_form(side_number(unit->side)); + write_num_prop(key(K_Z), unit->z, 0, FALSE, FALSE); + write_str_prop(key(K_N), unit->name, NULL, FALSE, FALSE); + write_num_prop(key(K_OS), side_number(unit->origside), + side_number(unit->side), FALSE, FALSE); + /* Maybe write the unit's id. */ + if (module->def_all + || module->def_unit_ids + || (unit->occupant + && unit->name == NULL + && unit_symbol(unit) == lispnil)) + write_num_prop(key(K_SHARP), unit->id, 0, FALSE, FALSE); + /* Need this to get back into the right transport. */ + if (unit->transport) { + if (unit_symbol(unit->transport) != lispnil + && !module->def_all + && !module->def_unit_ids) { + write_lisp_prop(key(K_IN), + unit_symbol(unit->transport), + lispnil, FALSE, TRUE, FALSE); + } else if (unit->transport->name + && !module->def_all + && !module->def_unit_ids) { + write_str_prop(key(K_IN), unit->transport->name, + NULL, FALSE, FALSE); + } else { + write_num_prop(key(K_IN), unit->transport->id, + 0, FALSE, FALSE); + } + } + /* Always need this, because occupants may reference. */ + write_lisp_prop(key(K_SYM), unit_symbol(unit), lispnil, + FALSE, TRUE, FALSE); + /* Write optional info about the units. */ + if (module->def_all || module->def_unit_props) + write_unit_properties(unit); + if (module->def_all || module->def_unit_acts) + write_unit_act(unit); + if (module->def_all || module->def_unit_plans) + write_unit_plan(unit); + /* close the unit out */ + end_form(); + newline_form(); + Dprintf("Wrote %s\n", unit_desig(unit)); + } + } + newline_form(); + } + Dprintf("... Done writing units.\n"); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: goal.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/unit/goal.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** goal.cc 29 May 2006 22:43:09 -0000 1.1 --- goal.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2005-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 194,197 **** --- 194,215 ---- } + void + write_goal(Goal *goal, int keyword) + { + int i, numargs; + char *argtypes; + + space_form(); + start_form(key((enum keywords)keyword)); + add_num_to_form(side_number(goal->side)); + add_num_to_form(goal->tf); + add_to_form(goaldefns[goal->type].name); + argtypes = goaldefns[goal->type].argtypes; + numargs = strlen(argtypes); + for (i = 0; i < numargs; ++i) + add_num_to_form(goal->args[i]); + end_form(); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: task.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/unit/task.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** task.cc 29 May 2006 22:43:09 -0000 1.1 --- task.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2006 Eric A. McDonald *************** *** 368,371 **** --- 368,391 ---- } + void + write_task(Task *task) + { + int i, numargs; + char *argtypes; + + if (!is_task_type(task->type)) { + run_warning("Bad task type %d while writing, skipping it", task->type); + return; + } + start_form(taskdefns[task->type].name); + add_num_to_form(task->execnum); + add_num_to_form(task->retrynum); + argtypes = taskdefns[task->type].argtypes; + numargs = strlen(argtypes); + for (i = 0; i < numargs; ++i) + add_num_to_form(task->args[i]); + end_form(); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: action.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/unit/action.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** action.cc 29 May 2006 22:43:09 -0000 1.1 --- action.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 177,180 **** --- 177,226 ---- } + void + write_action(Action *action, int id) + { + int atype, i, slen; + + atype = action->type; + start_form(actiondefns[atype].name); + slen = strlen(actiondefns[atype].argtypes); + for (i = 0; i < slen; ++i) + add_num_to_form(action->args[i]); + if (action->actee != 0 && action->actee != id) + add_num_to_form(action->actee); + end_form(); + } + + void + write_unit_act(Unit *unit) + { + int acp = u_acp(unit->type); + ActorState *act = unit->act; + + /* Actor state is kind of meaningless for dead units. */ + if (!alive(unit)) + return; + if (act != NULL + && (act->acp != acp + || act->initacp != acp + || act->nextaction.type != ACTION_NONE + || act->actualmoves)) { + if (1) { + newline_form(); + space_form(); + } + write_num_prop(key(K_ACP), act->acp, acp, FALSE, FALSE); + write_num_prop(key(K_ACP0), act->initacp, acp, FALSE, FALSE); + write_num_prop(key(K_AM), act->actualmoves, 0, FALSE, FALSE); + if (act->nextaction.type != ACTION_NONE) { + space_form(); + start_form(key(K_A)); + space_form(); + write_action(&(act->nextaction), unit->id); + end_form(); + } + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: plan.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/unit/plan.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** plan.cc 29 May 2006 22:43:09 -0000 1.1 --- plan.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 39,42 **** --- 39,55 ---- NAMESPACE_GDL_BEGIN + // Global Variables + + char *plantypenames[] = { + + #undef DEF_PLAN + #define DEF_PLAN(NAME,code) NAME, + + #include "gdl/unit/plan.def" + + NULL + + }; + // Local Functions: Queries *************** *** 56,60 **** { int i; - extern char *plantypenames[]; for (i = 0; plantypenames[i] != NULL; ++i) --- 69,72 ---- *************** *** 238,241 **** --- 250,298 ---- } + void + write_unit_plan(Unit *unit) + { + Task *task; + Plan *plan = unit->plan; + + /* The plan is kind of meaningless for dead units. */ + if (!alive(unit)) + return; + if (plan) { + if (1) { + newline_form(); + space_form(); + } + space_form(); + start_form(key(K_PLAN)); + add_to_form(plantypenames[plan->type]); + add_num_to_form(plan->creation_turn); + write_num_prop(key(K_INITIAL_TURN), plan->initial_turn, 0, FALSE, FALSE); + write_num_prop(key(K_FINAL_TURN), plan->final_turn, 0, FALSE, FALSE); + write_bool_prop(key(K_ASLEEP), plan->asleep, FALSE, FALSE, FALSE); + write_bool_prop(key(K_RESERVE), plan->reserve, FALSE, FALSE, FALSE); + write_bool_prop(key(K_DELAYED), plan->delayed, FALSE, FALSE, FALSE); + write_bool_prop(key(K_WAIT), plan->waitingfortasks, FALSE, FALSE, FALSE); + write_bool_prop(key(K_AI_CONTROL), plan->aicontrol, TRUE, FALSE, FALSE); + write_bool_prop(key(K_SUPPLY_ALARM), plan->supply_alarm, TRUE, FALSE, FALSE); + write_bool_prop(key(K_SUPPLY_IS_LOW), plan->supply_is_low, FALSE, FALSE, FALSE); + write_bool_prop(key(K_WAIT_TRANSPORT), plan->waitingfortransport, FALSE, FALSE, FALSE); + if (plan->maingoal) + write_goal(plan->maingoal, K_GOAL); + if (plan->formation) + write_goal(plan->formation, K_FORMATION); + if (plan->tasks) { + space_form(); + start_form(key(K_TASKS)); + for_all_tasks(plan, task) { + space_form(); + write_task(task); + } + end_form(); + } + end_form(); + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: pastunit.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/unit/pastunit.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pastunit.cc 29 May 2006 22:43:09 -0000 1.1 --- pastunit.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2006 Eric A. McDonald *************** *** 34,37 **** --- 34,38 ---- #include "gdl/types.h" + #include "gdl/desc.h" #include "gdl/unit/pastunit.h" #include "gdl/side/side.h" *************** *** 53,56 **** --- 54,119 ---- static int next_past_unit_id = -2; + // Local Variables: Buffers + + static char *past_unitbuf = NULL; + + // Queries + + PastUnit * + find_past_unit(int n) + { + PastUnit *pastunit; + + for (pastunit = past_unit_list; pastunit != NULL; pastunit = pastunit->next) { + if (pastunit->id == n) + return pastunit; + } + return NULL; + } + + char * + past_unit_handle(Side *side, PastUnit *past_unit) + { + char *utypename; + Side *side2; + + if (past_unitbuf == NULL) + past_unitbuf = (char *)xmalloc(BUFSIZE); + /* Handle various weird situations. */ + if (past_unit == NULL) + return "???"; + /* Decide how to identify the side. */ + side2 = past_unit->side; + if (side2 == NULL) { + sprintf(past_unitbuf, "the "); + } else if (side2 == side) { + sprintf(past_unitbuf, "your "); + } else { + /* If the side adjective is a genitive (ends in 's, s' or z') + we should skip the definite article. */ + int len = strlen(side_adjective(side2)); + char *end = side_adjective(side2) + len - 2; + + if (strcmp(end, "'s") != 0 + && strcmp(end, "s'") != 0 + && strcmp(end, "z'") != 0) + sprintf(past_unitbuf, "the "); + sprintf(past_unitbuf, side_adjective(side2)); + strcat(past_unitbuf, " "); + } + /* Now add the past_unit's unique description. */ + utypename = u_type_name(past_unit->type); + if (past_unit->name) { + tprintf(past_unitbuf, "%s %s", utypename, past_unit->name); + } else if (past_unit->number > 0) { + tprintf(past_unitbuf, "%d%s %s", + past_unit->number, ordinal_suffix(past_unit->number), + utypename); + } else { + strcat(past_unitbuf, utypename); + } + return past_unitbuf; + } + // Lifecycle Management *************** *** 135,138 **** --- 198,217 ---- } + void + write_past_unit(PastUnit *pastunit) + { + start_form(key(K_EXU)); + add_num_to_form(pastunit->id); + add_to_form(shortest_escaped_name(pastunit->type)); + add_num_to_form(pastunit->x); + add_num_to_form(pastunit->y); + add_num_to_form(side_number(pastunit->side)); + write_num_prop(key(K_Z), pastunit->z, 0, FALSE, FALSE); + write_str_prop(key(K_N), pastunit->name, NULL, FALSE, FALSE); + write_num_prop(key(K_NB), pastunit->number, 0, FALSE, FALSE); + end_form(); + newline_form(); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END |
From: Eric M. <eri...@us...> - 2006-06-02 16:57:48
|
Update of /cvsroot/xconq/xconq/src/gdl/gamearea In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv22145/gamearea Modified Files: area.cc feature.cc layers.cc Log Message: Add GDL serialization support. Fix copyrights. Fix automakefile. Index: feature.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/gamearea/feature.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** feature.cc 29 May 2006 19:24:53 -0000 1.1 --- feature.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 38,49 **** NAMESPACE_GDL_BEGIN ! // Local Variables - //! List of features. Feature *featurelist = NULL; //! Tail of list of features. ! Feature *last_feature = NULL; //! Count of features created. ! int numfeatures; // Local Variables: Counters --- 38,51 ---- NAMESPACE_GDL_BEGIN ! // Global Variables Feature *featurelist = NULL; + + // Local Variables + //! Tail of list of features. ! static Feature *last_feature = NULL; //! Count of features created. ! static int numfeatures; // Local Variables: Counters *************** *** 51,55 **** //! ID of next feature to be created. /*! Feature id 0 means no geographical feature defined. */ ! int nextfid = 1; // Queries --- 53,57 ---- //! ID of next feature to be created. /*! Feature id 0 means no geographical feature defined. */ ! static int nextfid = 1; // Queries Index: area.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/gamearea/area.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** area.cc 29 May 2006 19:24:53 -0000 1.1 --- area.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 37,40 **** --- 37,41 ---- #include "gdl/gamearea/area.h" #include "gdl/world.h" + #include "gdl/module.h" NAMESPACE_XCONQ_BEGIN *************** *** 525,528 **** --- 526,586 ---- } + void + write_areas(Module *module) + { + int all = module->def_all, compress = module->compress_layers; + + newline_form(); + /* Write the basic dimensions. */ + start_form(key(K_AREA)); + /* K_WIDTH, K_HEIGHT written if nonzero. */ + if (area.width > 0 || area.height > 0) { + add_num_to_form((doreshape ? reshaper->final_width : area.width)); + add_num_to_form((doreshape ? reshaper->final_height : area.height)); + } + /* Write all the scalar properties. */ + write_num_prop(key(K_LATITUDE), area.latitude, 0, 0, FALSE); + write_num_prop(key(K_LONGITUDE), area.longitude, 0, 0, FALSE); + write_num_prop(key(K_PROJECTION), area.projection, 0, 0, FALSE); + write_num_prop(key(K_CELL_WIDTH), area.cellwidth, 0, 0, FALSE); + if (area.sunx != area.width / 2 || area.suny != area.halfheight) { + start_form(key(K_SUN)); + add_num_to_form(area.sunx); + add_num_to_form(area.suny); + end_form(); + newline_form(); + } + write_lisp_prop(key(K_TEMPERATURE_YEAR_CYCLE), area.temp_year, + lispnil, FALSE, FALSE, TRUE); + write_str_prop(key(K_IMAGE_NAME), area.image_name, + "", FALSE, TRUE); + end_form(); + newline_form(); + /* Write the area's layers, each as a separate form. */ + if (all || module->def_area_terrain) + write_area_terrain(compress); + if (all || module->def_area_terrain) + write_area_aux_terrain(compress); + if (all || module->def_area_misc) + write_area_features(compress); + if (all || module->def_area_misc) + write_area_elevations(compress); + if (all || module->def_area_misc) + write_area_people_sides(compress); + if (all || module->def_area_misc) + write_area_control_sides(compress); + if (all || module->def_area_material) + write_area_materials(compress); + if (all || module->def_area_weather) + write_area_temperatures(compress); + if (all || module->def_area_weather) + write_area_clouds(compress); + if (all || module->def_area_weather) + write_area_winds(compress); + /* It is alloc_area_terrain that handles the user layer. */ + if (all || module->def_area_terrain) + write_area_users(compress); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: layers.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/gamearea/layers.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** layers.cc 29 May 2006 19:24:53 -0000 1.1 --- layers.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 36,40 **** --- 36,42 ---- #include "gdl/dir.h" #include "gdl/unit/unit.h" + #include "gdl/side/side.h" #include "gdl/gamearea/area.h" + #include "gdl/world.h" #include "gdl/module.h" *************** *** 58,62 **** static int ignore_specials; ! // Local Function Declarations //! Read and decode textual run-length encodings. --- 60,64 ---- static int ignore_specials; ! // Local Function Declarations: GDL I/O //! Read and decode textual run-length encodings. *************** *** 66,71 **** --- 68,164 ---- Obj *contents, void (*setter)(int, int, int), short *chartable); + //! Translate coordinate of reshaped area to one in original area. + static int original_point(int x1, int y1, int *x2p, int *y2p); + + //! Elevation at position minus minimum elevation. + static int fn_elevation_at_offset(int x, int y); + + //! Write run of run-length encoding. + /*! + Write a single run, using the most compact encoding possible. + 0 - 29 is 'a' - '~', 30 - 63 is ':' - '[' + */ + static void write_run(int run, int val); + // Game Area Layer Accessors + int + fn_terrain_at(int x, int y) + { + return terrain_at(x, y); + } + + int + fn_aux_terrain_at(int x, int y) + { + return aux_terrain_at(x, y, tmpttype); + } + + int + fn_feature_at(int x, int y) + { + return raw_feature_at(x, y); + } + + int + fn_elevation_at(int x, int y) + { + return elev_at(x, y); + } + + int + fn_people_side_at(int x, int y) + { + return people_side_at(x, y); + } + + int + fn_control_side_at(int x, int y) + { + return control_side_at(x, y); + } + + int + fn_material_at(int x, int y) + { + return material_at(x, y, tmpmtype); + } + + int + fn_temperature_at(int x, int y) + { + return temperature_at(x, y); + } + + int + fn_raw_cloud_at(int x, int y) + { + return raw_cloud_at(x, y); + } + + int + fn_raw_cloud_bottom_at(int x, int y) + { + return raw_cloud_bottom_at(x, y); + } + + int + fn_raw_cloud_height_at(int x, int y) + { + return raw_cloud_height_at(x, y); + } + + int + fn_raw_wind_at(int x, int y) + { + return raw_wind_at(x, y); + } + + int + fn_user_at(int x, int y) + { + return user_at(x, y); + } + void fn_set_terrain_at(int x, int y, int val) *************** *** 772,775 **** --- 865,1294 ---- } + static + int + original_point(int x1, int y1, int *x2p, int *y2p) + { + *x2p = (((x1 - reshaper->final_subarea_x) * reshaper->subarea_width ) + / reshaper->final_subarea_width ) + reshaper->subarea_x; + *y2p = (((y1 - reshaper->final_subarea_y) * reshaper->subarea_height) + / reshaper->final_subarea_height) + reshaper->subarea_y; + return inside_area(*x2p, *y2p); + } + + static + int + fn_elevation_at_offset(int x, int y) + { + return (elev_at(x, y) - area.minelev); + } + + static + void + write_run(int run, int val) + { + if (run > 1) { + add_num_to_form_no_space(run); + if (!between(0, val, 63)) + add_char_to_form('*'); + } + if (between(0, val, 29)) { + add_char_to_form(val + 'a'); + } else if (between(30, val, 63)) { + add_char_to_form(val - 30 + ':'); + } else { + add_num_to_form_no_space(val); + add_char_to_form(','); + } + } + + void + write_rle(int (*datafn)(int, int), int lo, int hi, int (*translator)(int), + int compress) + { + int width, height, x, y, x0, y0, run, runval, val, trval; + int numbad = 0; + + width = area.width; height = area.height; + if (doreshape) { + width = reshaper->final_width; height = reshaper->final_height; + } + /* Iterate through the rows from the top down. */ + for (y = height - 1; y >= 0; --y) { + space_form(); + space_form(); + add_char_to_form('"'); + run = 0; + x0 = 0; y0 = y; + if (doreshape) + original_point(0, y, &x0, &y0); + val = (*datafn)(x0, y0); + /* Zero out anything not in the world, unless reshaping. */ + if (!doreshape && !in_area(x0, y0)) + val = 0; + /* Check that the data falls within bounds, clip if not. */ + if (lo <= hi && !between(lo, val, hi) && in_area(x0, y0)) { + ++numbad; + if (val < lo) + val = lo; + if (val > hi) + val = hi; + } + runval = val; + for (x = 0; x < width; ++x) { + x0 = x; y0 = y; + if (doreshape) + original_point(x, y, &x0, &y0); + val = (*datafn)(x0, y0); + /* Zero out anything not in the world, unless reshaping. */ + if (!doreshape && !in_area(x0, y0)) + val = 0; + /* Check that the data falls within bounds, clip if not. */ + if (lo <= hi && !between(lo, val, hi) && in_area(x0, y0)) { + ++numbad; + if (val < lo) + val = lo; + if (val > hi) + val = hi; + } + if (val == runval && compress) { + run++; + } else { + trval = (translator != NULL ? (*translator)(runval) : runval); + write_run(run, trval); + /* Start a new run. */ + runval = val; + run = 1; + } + } + /* Finish off the row. */ + trval = (translator != NULL ? (*translator)(val) : val); + write_run(run, trval); + add_char_to_form('"'); + newline_form(); + } + if (numbad > 0) { + run_warning("%d values not between %d and %d", numbad, lo, hi); + } + } + + void + write_area_terrain(int compress) + { + int t; + + /* Terrain might not be set up when downloading at beginning of game, + don't try to write if so. */ + if (area.terrain == NULL) + return; + start_form(key(K_AREA)); + space_form(); + start_form(key(K_TERRAIN)); + newline_form(); + space_form(); + start_form(key(K_BY_NAME)); + for_all_terrain_types(t) { + /* Break the list into groups of 5 per line. */ + if (t % 5 == 0) { + newline_form(); + space_form(); + space_form(); + space_form(); + } + space_form(); + start_form(escaped_symbol(t_type_name(t))); + add_num_to_form(t); + end_form(); + } + end_form(); + newline_form(); + write_rle(fn_terrain_at, 0, numttypes - 1, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + + void + write_area_aux_terrain(int compress) + { + int t; + + for_all_terrain_types(t) { + if (aux_terrain_defined(t)) { + start_form(key(K_AREA)); + space_form(); + start_form(key(K_AUX_TERRAIN)); + add_to_form(escaped_symbol(t_type_name(t))); + newline_form(); + tmpttype = t; + write_rle(fn_aux_terrain_at, 0, 127, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + } + } + + void + write_area_features(int compress) + { + Feature *feature; + + if (featurelist == NULL || !features_defined()) + return; + start_form(key(K_AREA)); + space_form(); + start_form(key(K_FEATURES)); + space_form(); + start_form(""); + newline_form(); + /* Dump out the list of features first. */ + for_all_features(feature) { + space_form(); + space_form(); + space_form(); + start_form(""); + add_num_to_form(feature->id); + add_to_form(escaped_string(feature->feattype)); + add_to_form(escaped_string(feature->name)); + end_form(); + newline_form(); + } + space_form(); + space_form(); + end_form(); + newline_form(); + /* Now record which features go with which cells. */ + write_rle(fn_feature_at, 0, -1, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + + void + write_area_elevations(int compress) + { + if (!elevations_defined()) + return; + start_form(key(K_AREA)); + space_form(); + start_form(key(K_ELEVATIONS)); + if (area.minelev != 0) { + space_form(); + start_form(key(K_XFORM)); + add_num_to_form(1); + add_num_to_form(area.minelev); + end_form(); + } + newline_form(); + write_rle(fn_elevation_at_offset, 0, area.maxelev - area.minelev, + NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + + void + write_area_people_sides(int compress) + { + Side *side; + + if (!people_sides_defined()) + return; + start_form(key(K_AREA)); + space_form(); + start_form(key(K_PEOPLE_SIDES)); + newline_form(); + space_form(); + space_form(); + start_form(key(K_BY_NAME)); + for_all_sides(side) { + /* Break the list into groups of 5 per line. */ + if (side_number(side) % 5 == 0) { + newline_form(); + space_form(); + space_form(); + space_form(); + } + space_form(); + start_form(""); + add_num_to_form(side_number(side)); /* should be symbol */ + add_num_to_form(side_number(side)); + end_form(); + } + end_form(); + newline_form(); + /* Value of NOBODY is guaranteed to be the largest valid. */ + write_rle(fn_people_side_at, 0, NOBODY, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + + void + write_area_control_sides(int compress) + { + Side *side; + + if (!control_sides_defined()) + return; + start_form(key(K_AREA)); + space_form(); + start_form(key(K_CONTROL_SIDES)); + newline_form(); + space_form(); + space_form(); + start_form(key(K_BY_NAME)); + for_all_sides(side) { + /* Break the list into groups of 5 per line. */ + if (side_number(side) % 5 == 0) { + newline_form(); + space_form(); + space_form(); + space_form(); + } + space_form(); + start_form(""); + add_num_to_form(side_number(side)); /* should be symbol */ + add_num_to_form(side_number(side)); + end_form(); + } + end_form(); + newline_form(); + /* Value of NOCONTROL is guaranteed to be the largest valid. */ + write_rle(fn_control_side_at, 0, NOCONTROL, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + + void + write_area_materials(int compress) + { + int m; + + if (any_cell_materials_defined()) { + for_all_material_types(m) { + if (cell_material_defined(m)) { + start_form(key(K_AREA)); + space_form(); + start_form(key(K_MATERIAL)); + add_to_form(escaped_symbol(m_type_name(m))); + newline_form(); + tmpmtype = m; + write_rle(fn_material_at, 0, 127, NULL, compress); + end_form(); + end_form(); + newline_form(); + } + } + } + } + + void + write_area_temperatures(int compress) + { + if (!temperatures_defined()) + return; + start_form(key(K_AREA)); + space_form(); + start_form(key(K_TEMPERATURES)); + newline_form(); + write_rle(fn_temperature_at, -9999, 9999, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + + void + write_area_clouds(int compress) + { + if (clouds_defined()) { + start_form(key(K_AREA)); + space_form(); + start_form(key(K_CLOUDS)); + newline_form(); + write_rle(fn_raw_cloud_at, 0, 127, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + if (cloud_bottoms_defined()) { + start_form(key(K_AREA)); + space_form(); + start_form(key(K_CLOUD_BOTTOMS)); + newline_form(); + write_rle(fn_raw_cloud_bottom_at, 0, 9999, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + if (cloud_heights_defined()) { + start_form(key(K_AREA)); + space_form(); + start_form(key(K_CLOUD_HEIGHTS)); + newline_form(); + write_rle(fn_raw_cloud_height_at, 0, 9999, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + } + + void + write_area_winds(int compress) + { + if (winds_defined()) { + start_form(key(K_AREA)); + space_form(); + start_form(key(K_WINDS)); + newline_form(); + write_rle(fn_raw_wind_at, -32767, 32767, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + } + + void + write_area_users(int compress) + { + extern int nextid; + + if (!user_defined()) + return; + start_form(key(K_AREA)); + space_form(); + start_form(key(K_USER)); + newline_form(); + write_rle(fn_user_at, NOUSER, nextid, NULL, compress); + space_form(); + space_form(); + end_form(); + end_form(); + newline_form(); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END |
From: Eric M. <eri...@us...> - 2006-06-02 16:57:48
|
Update of /cvsroot/xconq/xconq/src/gdl/media In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv22145/media Modified Files: imf.cc img.cc Log Message: Add GDL serialization support. Fix copyrights. Fix automakefile. Index: imf.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/media/imf.cc,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** imf.cc 30 May 2006 02:49:02 -0000 1.3 --- imf.cc 2 Jun 2006 16:57:43 -0000 1.4 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2001 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2001 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald *************** *** 34,37 **** --- 34,45 ---- #include "gdl/media/imf.h" + #include "gdl/module.h" + + // Local Constant Macros + + //! RGB above this value should be considered white. + #define WHITE_THRESHOLD (65535 - 256) + //! RGB below this value should be considered black. + #define BLACK_THRESHOLD (0 + 255) NAMESPACE_XCONQ_BEGIN *************** *** 43,46 **** --- 51,73 ---- int numimages = 0; + ImageFamily **recorded_imfs; + int num_recorded_imfs; + + // Local Variables: Behavior Options + + short write_synthetic_also; + + // Local Function Declarations: Sorting + + //! Compare two GDL image families. + static int image_name_compare(const void *imf1, const void *imf2); + + //! Sort all recorded images. + /*! + The comparison function for the image list just does "strcmp" order + and *requires* that all image families be named and named uniquely. + */ + static void sort_all_recorded_images(void); + // Local Function Declarations: Lifecycle Management *************** *** 48,51 **** --- 75,104 ---- static ImageFamily *new_imf(char *name); + // Local Function Declarations: GDL I/O + + //! Write contents of GDL palette to file. + static void write_palette_contents( + FILE *fp, Obj *palette, int *rawpalette, int numcolors); + + //! Does color image match mono equivalent of it? + /*! + Study an ostensibly color image to see if its color table includes + black and white only (white first, then black), and if its data is + the same as the mono version of the image. + */ + static int color_matches_mono(Image *img); + //! Write color to file. + static void write_color(FILE *fp, int n, int r, int g, int b); + //! Write bitmap to file. + static void write_bitmap( + FILE *fp, char *subtyp, int w, int h, Obj *data, char *rawdata); + //! Write pixmap to file. + static void write_pixmap( + FILE *fp, + int w, int h, int aw, int ah, + int pixelsize, int orig_pixelsize, + Obj *palette, int *rawpalette, int numcolors, + Obj *lispdata, char *rawdata); + // Queries *************** *** 122,125 **** --- 175,196 ---- } + // Sorting + + static + int + image_name_compare(const void *imf1, const void *imf2) + { + return strcmp((*((ImageFamily **) imf1))->name, + (*((ImageFamily **) imf2))->name); + } + + static + void + sort_all_recorded_images(void) + { + qsort(&(recorded_imfs[0]), num_recorded_imfs, sizeof(ImageFamily *), + image_name_compare); + } + // Lifecycle Management *************** *** 138,141 **** --- 209,258 ---- // GDL I/O + void + parse_lisp_palette_entry(Obj *palentry, int *col, int *red, int *grn, int *blu) + { + Obj *colorcomp; + char *colorname; + + *col = c_number(car(palentry)); + colorcomp = cdr(palentry); + if (colorcomp == lispnil) + return; + if (symbolp(car(colorcomp)) || stringp(car(colorcomp))) { + colorname = c_string(car(colorcomp)); + *red = *grn = *blu = 0; + if (strcmp(colorname, "white") == 0) { + *red = *grn = *blu = 65535; + } else if (strcmp(colorname, "black") == 0) { + /* done */ + } else if (strcmp(colorname, "red") == 0) { + *red = 65535; + } else if (strcmp(colorname, "green") == 0) { + *grn = 65535; + } else if (strcmp(colorname, "blue") == 0) { + *blu = 65535; + } else { + init_warning("No color named \"%s\" found, substituting gray", + colorname); + *red = *grn = *blu = 128 * 256; + } + } else if (numberp(car(colorcomp))) { + *red = c_number(car(colorcomp)); + *grn = c_number(cadr(colorcomp)); + *blu = c_number(caddr(colorcomp)); + /* Assume small values are 8-bit rather than 16-bit colors. + (Works because as 16-bit colors, they would all be nearly + identical shades of black.) */ + if (*red < 256) + *red *= 256; + if (*grn < 256) + *grn *= 256; + if (*blu < 256) + *blu *= 256; + } else { + init_warning("palette color info is not a name or set of numbers, ignoring"); + } + } + ImageFamily * interp_imf(Obj *form) *************** *** 182,185 **** --- 299,726 ---- } + char * + find_color_name(int r, int g, int b) + { + if (r > WHITE_THRESHOLD + && g > WHITE_THRESHOLD + && b > WHITE_THRESHOLD) + return "white"; + else if (r < BLACK_THRESHOLD + && g < BLACK_THRESHOLD + && b < BLACK_THRESHOLD) + return "black"; + else if (r > WHITE_THRESHOLD + && g < BLACK_THRESHOLD + && b < BLACK_THRESHOLD) + return "red"; + else if (r < BLACK_THRESHOLD + && g > WHITE_THRESHOLD + && b < BLACK_THRESHOLD) + return "green"; + else if (r < BLACK_THRESHOLD + && g < BLACK_THRESHOLD + && b > WHITE_THRESHOLD) + return "blue"; + else + return NULL; + } + + static + void + write_palette_contents(FILE *fp, Obj *palette, int *rawpalette, int numcolors) + { + int len, i, col, red, grn, blu; + Obj *restpal; + + len = (palette != lispnil ? length(palette) : numcolors); + if (len > 2) + fprintf(fp, "\n "); + fprintf(fp, " (%s", keyword_name(K_PALETTE)); + if (palette != lispnil) { + for_all_list(palette, restpal) { + parse_lisp_palette_entry(car(restpal), &col, &red, &grn, &blu); + if (len > 2) + fprintf(fp, "\n "); + write_color(fp, col, red, grn, blu); + } + } else if (rawpalette != NULL) { + for (i = 0; i < numcolors; i++) { + if (len > 2) + fprintf(fp, "\n "); + write_color(fp, rawpalette[4*i], + rawpalette[4*i+1], rawpalette[4*i+2], rawpalette[4*i+3]); + } + } else { + fprintf(fp, " #| no palette? |# "); + } + fprintf(fp, ")"); + } + + static + int + color_matches_mono(Image *img) + { + int i, cj, mj, rowbytes, numbytes, cbyte, mbyte; + int col[2], red[2], grn[2], blu[2]; + char *cdatastr = NULL, *mdatastr = NULL; + Obj *clispdata = img->colrdata, *mlispdata = img->monodata, *palette; + + if (img->pixelsize != 1) + return FALSE; + + /* No match possible if not a black-white-only palette. */ + if (img->numcolors > 2) + return FALSE; + + if (img->rawpalette != NULL) { + for (i = 0; i < 2; i++) { + col[i] = img->rawpalette[4*i+0]; + red[i] = img->rawpalette[4*i+1]; + grn[i] = img->rawpalette[4*i+2]; + blu[i] = img->rawpalette[4*i+3]; + } + } else if (img->palette != lispnil) { + palette = img->palette; + parse_lisp_palette_entry(car(palette), &col[0], + &red[0], &grn[0], &blu[0]); + if (cdr(palette) == lispnil) { + /* If only one color in the palette, say the other one is + black. */ + col[1] = 1; + red[1] = grn[1] = blu[1] = 0; + /* If the one color is black, say it's white. */ + if (col[0] == 0 + && red[0] < BLACK_THRESHOLD + && grn[0] < BLACK_THRESHOLD + && blu[0] < BLACK_THRESHOLD) { + col[0] = 0; + red[0] = grn[0] = blu[0] = 65535; + } + } else { + /* Parse the second entry in the palette. */ + parse_lisp_palette_entry(cadr(palette), &col[1], + &red[1], &grn[1], &blu[1]); + } + } else { + return FALSE; + } + + if (!(col[0] == 0 + && red[0] > WHITE_THRESHOLD + && grn[0] > WHITE_THRESHOLD + && blu[0] > WHITE_THRESHOLD + && col[1] == 1 + && red[1] < BLACK_THRESHOLD + && grn[1] < BLACK_THRESHOLD + && blu[1] < BLACK_THRESHOLD)) + return FALSE; + + /* Now compare the contents. */ + rowbytes = computed_rowbytes(img->w, 1); + numbytes = img->h * rowbytes; + cj = mj = 0; + for (i = 0; i < numbytes; ++i) { + /* Extract one byte of the color image. */ + if (clispdata != lispnil) { + if (cdatastr == NULL || cdatastr[cj] == '\0') { + if (!stringp(car(clispdata))) + break; + cdatastr = c_string(car(clispdata)); + cj = 0; + clispdata = cdr(clispdata); + } + if (cdatastr[cj] == '/') + ++cj; + cbyte = hextoi(cdatastr[cj]) * 16 + hextoi(cdatastr[cj+1]); + cj += 2; + } else if (img->rawcolrdata != NULL) { + cbyte = (img->rawcolrdata)[i]; + } else { + return FALSE; + } + /* Extract one byte of the mono image. */ + if (mlispdata != lispnil) { + if (mdatastr == NULL || mdatastr[mj] == '\0') { + if (!stringp(car(mlispdata))) + break; + mdatastr = c_string(car(mlispdata)); + mj = 0; + mlispdata = cdr(mlispdata); + } + if (mdatastr[mj] == '/') + ++mj; + mbyte = hextoi(mdatastr[mj]) * 16 + hextoi(mdatastr[mj+1]); + mj += 2; + } else if (img->rawmonodata != NULL) { + mbyte = (img->rawmonodata)[i]; + } else { + return FALSE; + } + /* Compare the bytes. */ + if (cbyte != mbyte) + return FALSE; + } + return TRUE; + } + + static + void + write_color(FILE *fp, int n, int r, int g, int b) + { + char *colorname; + + if (n >= 0) + fprintf(fp, " (%d", n); + colorname = find_color_name(r, g, b); + if (!empty_string(colorname)) { + /* Write color name. Note that we write as a symbol, so that + each instance of "white" doesn't become a separate string. */ + fprintf(fp, " %s", colorname); + } else { + /* Write individual color components. */ + fprintf(fp, " %d %d %d", r, g, b); + } + if (n >= 0) + fprintf(fp, ")"); + } + + static + void + write_bitmap(FILE *fp, char *subtyp, int w, int h, Obj *lispdata, + char *rawdata) + { + int dolisp, i, j = 0, rowbytes, numbytes, byte; + char *datastr = NULL; + + /* Lisp data overrides raw byte data. */ + dolisp = (lispdata != lispnil); + rowbytes = computed_rowbytes(w, 1); + numbytes = h * rowbytes; + fprintf(fp, "(%s", subtyp); + if (w > 16 || h > 16) + fprintf(fp, "\n "); + fprintf(fp, " \""); + for (i = 0; i < numbytes; ++i) { + if (i > 0 && i % 32 == 0) + fprintf(fp, "\"\n \""); + if (i > 0 && i % 32 != 0 && i % rowbytes == 0) + fprintf(fp, "/"); + if (dolisp) { + if (datastr == NULL || datastr[j] == '\0') { + if (!stringp(car(lispdata))) + break; + datastr = c_string(car(lispdata)); + j = 0; + lispdata = cdr(lispdata); + } + /* Ignore any slashes, they're for human readability. */ + if (datastr[j] == '/') + ++j; + byte = hextoi(datastr[j]) * 16 + hextoi(datastr[j+1]); + j += 2; + } else { + byte = rawdata[i]; + } + fprintf(fp, "%02x", (unsigned char) byte); + } + fprintf(fp, "\")"); + } + + static + void + write_pixmap(FILE *fp, int w, int h, int actualw, int actualh, + int pixelsize, int orig_pixelsize, + Obj *palette, int *rawpalette, int numcolors, + Obj *lispdata, char *rawdata) + { + int dolisp, i, j = 0, rowbytes, numbytes, byte; + char *datastr = NULL; + + actualw = (actualw != 0 ? actualw : w); + actualh = (actualh != 0 ? actualh : h); + dolisp = (lispdata != lispnil); + /* If the pixel size was mangled (Windows) we need to use the original pixel size. */ + rowbytes = computed_rowbytes(actualw, (orig_pixelsize ? orig_pixelsize : pixelsize)); + numbytes = actualh * rowbytes; + fprintf(fp, "(%s", keyword_name(K_COLOR)); + if (actualw != w || actualh != h) + fprintf(fp, " (%s %d %d)", keyword_name(K_ACTUAL), actualw, actualh); + /* (should not use orig_pixelsize if !dolisp?) Yes! See above. */ + fprintf(fp, " (%s %d)", keyword_name(K_PIXEL_SIZE), + (orig_pixelsize ? orig_pixelsize : pixelsize)); + if (palette != lispnil || (rawpalette && numcolors)) + write_palette_contents(fp, palette, rawpalette, numcolors); + fprintf(fp, "\n \""); + for (i = 0; i < numbytes; ++i) { + if (i > 0 && i % 32 == 0) + fprintf(fp, "\"\n \""); + if (i > 0 && i % 32 != 0 && i % rowbytes == 0) + fprintf(fp, "/"); + if (dolisp) { + if (datastr == NULL || datastr[j] == '\0') { + if (!stringp(car(lispdata))) + break; + datastr = c_string(car(lispdata)); + j = 0; + lispdata = cdr(lispdata); + } + if (datastr[j] == '/') + ++j; + byte = hextoi(datastr[j]) * 16 + hextoi(datastr[j+1]); + j += 2; + } else { + byte = rawdata[i]; + } + fprintf(fp, "%02x", (unsigned char) byte); + } + fprintf(fp, "\")"); + } + + void + write_imf(FILE *fp, ImageFamily *imf) + { + Obj *palent, *posdata; + Image *img; + + if (fp == NULL || imf == NULL) + return; + if (imf->name == NULL) { + fprintf(fp, "; garbage image family?\n"); + return; + } + if (imf->notes != lispnil) { + fprintf(fp, "(%s \"%s\"", keyword_name(K_IMF), imf->name); + fprintf(fp, "\n (%s ", keyword_name(K_NOTES)); + fprintlisp(fp, imf->notes); + fprintf(fp, "))\n"); + } + for_all_images(imf, img) { + if (img->monodata != lispnil + || img->maskdata != lispnil + || img->colrdata != lispnil + || img->filedata != lispnil + || img->rawmonodata != NULL + || img->rawmaskdata != NULL + || img->rawcolrdata != NULL + || (img->w == 1 && img->h == 1)) { + /* Skip over synthesized images. */ + if (img->synthetic && !write_synthetic_also) { + continue; + } + /* Skip over empty (undefined) 1 x 1 images. */ + if (img->w == 1 + && img->h == 1 + && img->rawpalette == NULL + && img->palette == lispnil) { + continue; + } + fprintf(fp, "(%s \"%s\"", keyword_name(K_IMF), imf->name); + fprintf(fp, " ("); + fprintf(fp, "(%d %d", img->w, img->h); + if (img->istile && !(img->w == 1 && img->h == 1)) + fprintf(fp, " %s", keyword_name(K_TILE)); + if (img->isterrain) + fprintf(fp, " %s", keyword_name(K_TERRAIN)); + if (img->isconnection) + fprintf(fp, " %s", keyword_name(K_CONNECTION)); + if (img->isborder) + fprintf(fp, " %s", keyword_name(K_BORDER)); + if (img->istransition) + fprintf(fp, " %s", keyword_name(K_TRANSITION)); + fprintf(fp, ")"); + if (img->numsubimages > 0) { + fprintf(fp, " (%s %d", keyword_name(K_X), img->numsubimages); + if (img->subx > 0 || img->suby > 0) + fprintf(fp, " %d %d", img->subx, img->suby); + fprintf(fp, ")"); + } + if (img->hexgridx > 0 && img->hexgridy > 0) { + fprintf(fp, " (%s %d %d)", keyword_name(K_HEXGRID), + img->hexgridx, img->hexgridy); + } + if (img->embedname) { + fprintf(fp, " (%s \"%s\")", + keyword_name(K_EMBED), img->embedname); + } + if (img->embedx >= 0 && img->embedy >= 0) { + fprintf(fp, " (%s %d %d)", + keyword_name(K_EMBED_AT), img->embedx, img->embedy); + } + if (img->embedw >= 0 && img->embedh >= 0) { + fprintf(fp, " (%s %d %d)", + keyword_name(K_EMBED_SIZE), img->embedw, img->embedh); + } + if (img->notes != lispnil) { + fprintf(fp, "\n (%s ", keyword_name(K_NOTES)); + fprintlisp(fp, img->notes); + fprintf(fp, ")\n "); + } + /* Write a single color if that's what this image is. */ + if (img->w == 1 && img->h == 1) { + if (img->rawpalette != NULL) { + write_color(fp, -1, + img->rawpalette[1], + img->rawpalette[2], + img->rawpalette[3]); + } else if (img->palette != lispnil) { + palent = cdr(car(img->palette)); + if (stringp(car(palent)) || symbolp(car(palent))) { + fprintf(fp, " %s", c_string(car(palent))); + } else { + write_color(fp, -1, + c_number(car(palent)), + c_number(cadr(palent)), + c_number(caddr(palent))); + } + } + } else if (img->filedata != lispnil) { + fprintf(fp, " (%s ", keyword_name(K_FILE)); + fprintf(fp, " \"%s\"", c_string(car(img->filedata))); + posdata = cdr(img->filedata); + if (posdata != lispnil) { + if (symbolp(car(posdata))) { + fprintf(fp, " %s", c_string(car(posdata))); + posdata = cdr(posdata); + } + fprintf(fp, " %d %d", + c_number(car(posdata)), c_number(cadr(posdata))); + } + fprintf(fp, ")"); + } else if ((img->colrdata != lispnil || img->rawcolrdata) + && !color_matches_mono(img)) { + fprintf(fp, "\n "); + write_pixmap(fp, img->w, img->h, img->actualw, img->actualh, + img->pixelsize, img->orig_pixelsize, + img->palette, img->rawpalette, img->numcolors, + img->colrdata, img->rawcolrdata); + } + if (img->monodata != lispnil || img->rawmonodata) { + fprintf(fp, "\n "); + write_bitmap(fp, keyword_name(K_MONO), img->w, img->h, + img->monodata, img->rawmonodata); + } + if (img->maskdata != lispnil || img->rawmaskdata) { + fprintf(fp, "\n "); + write_bitmap(fp, keyword_name(K_MASK), img->w, img->h, + img->maskdata, img->rawmaskdata); + } + fprintf(fp, "))\n"); + } + } + } + + void + write_images(void) + { + int i; + + if (recorded_imfs == NULL || num_recorded_imfs == 0) + return; + sort_all_recorded_images(); + for (i = 0; i < num_recorded_imfs; ++i) { + write_imf(wfp, recorded_imfs[i]); + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: img.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/media/img.cc,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** img.cc 30 May 2006 02:49:02 -0000 1.2 --- img.cc 2 Jun 2006 16:57:43 -0000 1.3 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2001 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2001 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald |
From: Eric M. <eri...@us...> - 2006-06-02 16:57:47
|
Update of /cvsroot/xconq/xconq/src/gdl In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv22145 Modified Files: Makefile.am Makefile.in gvars.cc history.cc lisp.cc module.cc namer.cc pact.cc player.cc score.cc tables.cc types.cc world.cc Log Message: Add GDL serialization support. Fix copyrights. Fix automakefile. Index: gvars.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/gvars.cc,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** gvars.cc 23 May 2006 18:02:09 -0000 1.4 --- gvars.cc 2 Jun 2006 16:57:43 -0000 1.5 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2004-2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2004-2006 Eric A. McDonald *************** *** 233,236 **** --- 233,299 ---- } + void + write_globals(void) + { + int i, complete = FALSE; + Obj *val; + time_t now; + + /* Snapshot realtime values, but only after they've been set up. */ + if (g_elapsed_time() >= 0) { + time(&now); + set_g_elapsed_time(idifftime(now, game_start_in_real_time)); + } + + newline_form(); + + for (i = 0; vardefns[i].name != 0; ++i) { + if (debugging_state_sync + && strcmp(vardefns[i].name, "elapsed-real-time") == 0) + continue; + if (vardefns[i].intgetter != NULL) { + if (complete || (*(vardefns[i].intgetter))() != vardefns[i].dflt) { + start_form(key(K_SET)); + add_to_form(vardefns[i].name); + add_num_to_form((*(vardefns[i].intgetter))()); + end_form(); + newline_form(); + } + } else if (vardefns[i].strgetter != NULL) { + if (complete + || string_not_default((*(vardefns[i].strgetter))(), + vardefns[i].dfltstr)) { + start_form(key(K_SET)); + add_to_form(vardefns[i].name); + add_to_form(escaped_string((*(vardefns[i].strgetter))())); + end_form(); + newline_form(); + } + } else if (vardefns[i].objgetter != NULL) { + val = (*(vardefns[i].objgetter))(); + if (complete + || val != lispnil + /* Must write out explicit nil setting if the default + function is defined, so it won't re-run on startup. */ + || (val == lispnil && vardefns[i].dfltfn != NULL)) { + start_form(key(K_SET)); + add_to_form(vardefns[i].name); + space_form(); + /* Suppress evaluation upon readin. */ + add_to_form_no_space("'"); + add_form_to_form((*(vardefns[i].objgetter))()); + end_form(); + newline_form(); + } + } else { + #ifdef __cplusplus + throw "snafu"; + #else + abort(); + #endif + } + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: Makefile.in =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/Makefile.in,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** Makefile.in 29 May 2006 20:11:12 -0000 1.8 --- Makefile.in 2 Jun 2006 16:57:43 -0000 1.9 *************** *** 66,75 **** libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) ! libconq_gdl_la_DEPENDENCIES = unit/libconq_gdl_media.la \ unit/libconq_gdl_unit.la side/libconq_gdl_side.la \ ! side/libconq_gdl_gamearea.la am_libconq_gdl_la_OBJECTS = lisp.lo desc.lo dice.lo types.lo gvars.lo \ tables.lo dir.lo namer.lo pact.lo history.lo player.lo \ ! score.lo world.lo module.lo write.lo libconq_gdl_la_OBJECTS = $(am_libconq_gdl_la_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src/include --- 66,75 ---- libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) ! libconq_gdl_la_DEPENDENCIES = media/libconq_gdl_media.la \ unit/libconq_gdl_unit.la side/libconq_gdl_side.la \ ! gamearea/libconq_gdl_gamearea.la am_libconq_gdl_la_OBJECTS = lisp.lo desc.lo dice.lo types.lo gvars.lo \ tables.lo dir.lo namer.lo pact.lo history.lo player.lo \ ! score.lo world.lo module.lo libconq_gdl_la_OBJECTS = $(am_libconq_gdl_la_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src/include *************** *** 230,237 **** libconq_gdl_la_SOURCES = lisp.cc desc.cc dice.cc types.cc gvars.cc \ tables.cc dir.cc namer.cc pact.cc history.cc player.cc \ ! score.cc world.cc module.cc write.cc ! libconq_gdl_la_LIBADD = unit/libconq_gdl_media.la \ unit/libconq_gdl_unit.la side/libconq_gdl_side.la \ ! side/libconq_gdl_gamearea.la all: all-recursive --- 230,237 ---- libconq_gdl_la_SOURCES = lisp.cc desc.cc dice.cc types.cc gvars.cc \ tables.cc dir.cc namer.cc pact.cc history.cc player.cc \ ! score.cc world.cc module.cc ! libconq_gdl_la_LIBADD = media/libconq_gdl_media.la \ unit/libconq_gdl_unit.la side/libconq_gdl_side.la \ ! gamearea/libconq_gdl_gamearea.la all: all-recursive *************** *** 317,321 **** @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/world.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write.Plo@am__quote@ .cc.o: --- 317,320 ---- Index: player.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/player.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** player.cc 27 May 2006 23:31:33 -0000 1.1 --- player.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 8,12 **** Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 8,12 ---- Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 33,36 **** --- 33,37 ---- */ + #include "gdl/side/side.h" #include "gdl/player.h" *************** *** 170,173 **** --- 171,205 ---- } + void + write_player(Player *player) + { + start_form(key(K_PLAYER)); + add_num_to_form(player->id); + newline_form(); + space_form(); + write_str_prop(key(K_NAME), player->name, "", FALSE, TRUE); + write_str_prop(key(K_CONFIG_NAME), player->configname, "", FALSE, TRUE); + write_str_prop(key(K_DISPLAY_NAME), player->displayname, "", FALSE, TRUE); + write_str_prop(key(K_AI_TYPE_NAME), player->aitypename, "", FALSE, TRUE); + space_form(); + end_form(); + newline_form(); + } + + void + write_players(void) + { + Side *side; + + Dprintf("Will try to write players ...\n"); + for_all_sides(side) { + if (side->player != NULL) { + write_player(side->player); + Dprintf("Wrote player %s,\n", player_desig(side->player)); + } + } + Dprintf("... Done writing players.\n"); + } + // Game Setup Index: pact.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/pact.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pact.cc 27 May 2006 23:01:40 -0000 1.1 --- pact.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 101,104 **** --- 101,136 ---- } + void + write_agreement(Agreement *agreement) + { + start_form(key(K_AGREEMENT)); + add_num_to_form(agreement->id); + newline_form(); + space_form(); + write_str_prop(key(K_TYPE_NAME), agreement->agtype, "", FALSE, TRUE); + write_str_prop(key(K_NAME), agreement->name, "", FALSE, TRUE); + write_num_prop(key(K_STATE), agreement->state, 0, FALSE, TRUE); + write_lisp_prop(key(K_TERMS), agreement->terms, lispnil, FALSE, FALSE, TRUE); + write_num_prop(key(K_DRAFTERS), agreement->drafters, 0, FALSE, TRUE); + write_num_prop(key(K_PROPOSERS), agreement->proposers, 0, FALSE, TRUE); + write_num_prop(key(K_SIGNERS), agreement->signers, 0, FALSE, TRUE); + write_num_prop(key(K_WILLING_TO_SIGN), agreement->willing, 0, FALSE, TRUE); + write_num_prop(key(K_KNOWN_TO), agreement->knownto, 0, FALSE, TRUE); + write_num_prop(key(K_ENFORCEMENT), agreement->enforcement, 0, FALSE, TRUE); + space_form(); + end_form(); + newline_form(); + } + + void + write_agreements(void) + { + Agreement *ag; + + for_all_agreements(ag) { + write_agreement(ag); + } + } + #endif Index: world.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/world.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** world.cc 29 May 2006 20:11:12 -0000 1.1 --- world.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 38,41 **** --- 38,42 ---- #include "gdl/gamearea/area.h" #include "gdl/world.h" + #include "gdl/module.h" NAMESPACE_XCONQ_BEGIN *************** *** 51,54 **** --- 52,59 ---- int daynight = FALSE; + // Global Variables: Behavior Options + + int doreshape; + // Queries *************** *** 148,151 **** --- 153,182 ---- } + int + reshaped_point(int x1, int y1, int *x2p, int *y2p) + { + *x2p = (((x1 - reshaper->subarea_x) * reshaper->final_subarea_width ) + / reshaper->subarea_width ) + reshaper->final_subarea_x; + *y2p = (((y1 - reshaper->subarea_y) * reshaper->final_subarea_height) + / reshaper->subarea_height) + reshaper->final_subarea_y; + return TRUE; + } + + void + write_world(void) + { + newline_form(); + start_form(key(K_WORLD)); + /* K_CIRCUMFERENCE always written. */ + add_num_to_form((doreshape ? reshaper->final_circumference : world.circumference)); + write_num_prop(key(K_DAY_LENGTH), world.daylength, 1, FALSE, FALSE); + write_num_prop(key(K_YEAR_LENGTH), world.yearlength, 1, FALSE, FALSE); + write_num_prop(key(K_AXIAL_TILT), world.axial_tilt, 0, FALSE, FALSE); + write_num_prop(key(K_DAYLIGHT_FRACTION), world.daylight_fraction, 0, FALSE, FALSE); + write_num_prop(key(K_TWILIGHT_FRACTION), world.twilight_fraction, 0, FALSE, FALSE); + end_form(); + newline_form(); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: types.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/types.cc,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** types.cc 29 May 2006 14:22:03 -0000 1.5 --- types.cc 2 Jun 2006 16:57:43 -0000 1.6 *************** *** 34,37 **** --- 34,38 ---- #include "gdl/tables.h" + #include "gdl/module.h" // Function Macros: Game Entity Property Accessors *************** *** 523,526 **** --- 524,536 ---- } + char * + shortest_escaped_name(int u) + { + char *internalname = u_internal_name(u); + + sprintf(shortestbuf, "%s", escaped_symbol(internalname)); + return shortestbuf; + } + int could_be_on(int u, int t) *************** *** 1736,1739 **** --- 1746,2059 ---- } + void + write_utype_value_list(char *name, short *arr, int dflt, int addnewline) + { + int u, writeany; + + if (arr == NULL) + return; + writeany = FALSE; + for_all_unit_types(u) { + if (arr[u] != dflt) { + writeany = TRUE; + break; + } + } + if (!writeany) + return; + space_form(); + start_form(name); + for_all_unit_types(u) { + add_num_to_form(arr[u]); + } + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + + void + write_mtype_value_list(char *name, short *arr, int dflt, int addnewline) + { + int m, writeany; + + if (nummtypes == 0 || arr == NULL) + return; + writeany = FALSE; + for_all_material_types(m) { + if (arr[m] != dflt) { + writeany = TRUE; + break; + } + } + if (!writeany) + return; + space_form(); + start_form(name); + for_all_material_types(m) { + add_num_to_form(arr[m]); + } + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + + void + write_treasury_list(char *name, long *arr, int dflt, int addnewline) + { + int m, writeany; + + if (nummtypes == 0 || arr == NULL) + return; + writeany = FALSE; + for_all_material_types(m) { + if (arr[m] != dflt) { + writeany = TRUE; + break; + } + } + if (!writeany) + return; + space_form(); + start_form(name); + for_all_material_types(m) { + add_num_to_form(arr[m]); + } + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + + void + write_atype_value_list(char *name, short *arr, int dflt, int addnewline) + { + int a, writeany; + + if (numatypes == 0 || arr == NULL) + return; + writeany = FALSE; + for_all_advance_types(a) { + if (arr[a] != dflt) { + writeany = TRUE; + break; + } + } + if (!writeany) + return; + space_form(); + start_form(name); + for_all_advance_types(a) { + add_num_to_form(arr[a]); + } + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + + void + write_utype_string_list(char *name, char **arr, char *dflt, int addnewline) + { + int u, writeany; + + if (arr == NULL) + return; + writeany = FALSE; + for_all_unit_types(u) { + if (arr[u] != dflt /* bogus, should use strcmp */) { + writeany = TRUE; + break; + } + } + if (!writeany) + return; + space_form(); + start_form(name); + for_all_unit_types(u) { + add_to_form(escaped_string(arr[u])); + } + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + + void + write_type_name_list(int typ, int *flags, int dim) + { + int j, first = TRUE, listlen = 0; + + if (flags == NULL) + return; + for (j = 0; j < dim; ++j) + if (flags[j]) + ++listlen; + if (listlen > 1) + start_form(""); + for (j = 0; j < dim; ++j) { + if (flags[j]) { + if (first) + first = FALSE; + else + space_form(); + add_to_form_no_space(escaped_symbol(name_from_typ(typ, j))); + } + } + if (listlen > 1) + end_form(); + } + + void + write_types(void) + { + int u, m, t, i, ival; + char *name, *sval; + Obj *obj; + + /* (or write out all the default values first for doc, then + only write changed values) */ + + for_all_unit_types(u) { + start_form(key(K_UNIT_TYPE)); + name = shortest_escaped_name(u); + add_to_form(name); + newline_form(); + space_form(); + for (i = 0; utypedefns[i].name != NULL; ++i) { + /* Don't write out props used internally only, unless debugging. */ + if ((strncmp(utypedefns[i].name, "zz-", 3) == 0) && !Debug) + continue; + if (utypedefns[i].intgetter) { + ival = (*(utypedefns[i].intgetter))(u); + write_num_prop(utypedefns[i].name, ival, + utypedefns[i].dflt, FALSE, TRUE); + } else if (utypedefns[i].strgetter) { + sval = (*(utypedefns[i].strgetter))(u); + /* Special-case a couple possibly-redundant slots. */ + if (utypedefns[i].strgetter == u_type_name + && strcmp(name, sval) == 0) + continue; + if (utypedefns[i].strgetter == u_internal_name + && strcmp(name, sval) == 0) + continue; + write_str_prop(utypedefns[i].name, sval, + utypedefns[i].dfltstr, FALSE, TRUE); + } else { + obj = (*(utypedefns[i].objgetter))(u); + write_lisp_prop(utypedefns[i].name, obj, + lispnil, FALSE, FALSE, TRUE); + } + } + space_form(); + end_form(); + newline_form(); + } + newline_form(); + for_all_material_types(m) { + start_form(key(K_MATERIAL_TYPE)); + name = escaped_symbol(m_type_name(m)); + add_to_form(name); + newline_form(); + space_form(); + for (i = 0; mtypedefns[i].name != NULL; ++i) { + /* Don't write out props used internally only, unless debugging. */ + if ((strncmp(mtypedefns[i].name, "zz-", 3) == 0) && !Debug) + continue; + if (mtypedefns[i].intgetter) { + ival = (*(mtypedefns[i].intgetter))(m); + write_num_prop(mtypedefns[i].name, ival, + mtypedefns[i].dflt, FALSE, TRUE); + } else if (mtypedefns[i].strgetter) { + sval = (*(mtypedefns[i].strgetter))(m); + /* Special-case a a possibly-redundant slot. */ + if (mtypedefns[i].strgetter == m_type_name + && strcmp(name, sval) == 0) + continue; + write_str_prop(mtypedefns[i].name, sval, + mtypedefns[i].dfltstr, FALSE, TRUE); + } else { + obj = (*(mtypedefns[i].objgetter))(m); + write_lisp_prop(mtypedefns[i].name, obj, + lispnil, FALSE, FALSE, TRUE); + } + } + space_form(); + end_form(); + newline_form(); + } + newline_form(); + for_all_terrain_types(t) { + start_form(key(K_TERRAIN_TYPE)); + name = escaped_symbol(t_type_name(t)); + add_to_form(name); + newline_form(); + space_form(); + for (i = 0; ttypedefns[i].name != NULL; ++i) { + /* Don't write out props used internally only, unless debugging. */ + if ((strncmp(ttypedefns[i].name, "zz-", 3) == 0) && !Debug) + continue; + if (ttypedefns[i].intgetter) { + ival = (*(ttypedefns[i].intgetter))(t); + write_num_prop(ttypedefns[i].name, ival, + ttypedefns[i].dflt, FALSE, TRUE); + } else if (ttypedefns[i].strgetter) { + sval = (*(ttypedefns[i].strgetter))(t); + /* Special-case a a possibly-redundant slot. */ + if (ttypedefns[i].strgetter == t_type_name + && strcmp(name, sval) == 0) + continue; + write_str_prop(ttypedefns[i].name, sval, + ttypedefns[i].dfltstr, FALSE, TRUE); + } else { + obj = (*(ttypedefns[i].objgetter))(t); + write_lisp_prop(ttypedefns[i].name, obj, + lispnil, FALSE, FALSE, TRUE); + } + } + space_form(); + end_form(); + newline_form(); + } + for_all_advance_types(t) { + start_form(key(K_ADVANCE_TYPE)); + add_to_form(escaped_symbol(a_type_name(t))); + newline_form(); + space_form(); + for (i = 0; atypedefns[i].name != NULL; ++i) { + /* Don't write out props used internally only, unless debugging. */ + if ((strncmp(atypedefns[i].name, "zz-", 3) == 0) && !Debug) + continue; + if (atypedefns[i].intgetter) { + ival = (*(atypedefns[i].intgetter))(t); + write_num_prop(atypedefns[i].name, ival, + atypedefns[i].dflt, FALSE, TRUE); + } else if (atypedefns[i].strgetter) { + sval = (*(atypedefns[i].strgetter))(t); + /* Special-case a a possibly-redundant slot. */ + if (atypedefns[i].strgetter == a_type_name + && strcmp(name, sval) == 0) + continue; + write_str_prop(atypedefns[i].name, sval, + atypedefns[i].dfltstr, FALSE, TRUE); + } else { + obj = (*(atypedefns[i].objgetter))(t); + write_lisp_prop(atypedefns[i].name, obj, + lispnil, FALSE, FALSE, TRUE); + } + } + space_form(); + end_form(); + newline_form(); + } + newline_form(); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: lisp.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/lisp.cc,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** lisp.cc 27 May 2006 02:55:13 -0000 1.3 --- lisp.cc 2 Jun 2006 16:57:43 -0000 1.4 *************** *** 6,9 **** --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// + Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2004-2006 Eric A. McDonald *************** *** 40,43 **** --- 41,45 ---- #include "gdl/kernel.h" #include "gdl/ui.h" + #include "gdl/dice.h" #include "gdl/tables.h" #include "gdl/unit/unit.h" *************** *** 121,124 **** --- 123,129 ---- static char *escapedthingbuf; + //! Buffer for embedding forms in forms. + static char *onemorebuf; + // Local Function Declarations: Notifications *************** *** 294,297 **** --- 299,320 ---- } + int + string_not_default(char *str, char *dflt) + { + if (empty_string(dflt)) { + if (empty_string(str)) { + return FALSE; + } else { + return TRUE; + } + } else { + if (empty_string(str)) { + return TRUE; + } else { + return (strcmp(str, dflt) != 0); + } + } + } + // Queries: Attribution *************** *** 616,619 **** --- 639,658 ---- Obj * + replace_at_key(Obj *lis, char *key, Obj *newval) + { + Obj *rest, *bdgs, *bdg; + + for_all_list(lis, rest) { + bdgs = car(rest); + bdg = car(bdgs); + if (stringp(bdg) && strcmp(key, c_string(bdg)) == 0) { + set_cdr(bdgs, newval); + return lis; + } + } + return cons(cons(new_string(key), newval), lis); + } + + Obj * remove_from_list(Obj *element, Obj *lis) { *************** *** 2017,2094 **** } - - #if (0) // Temp disable. - - int - member(Obj *x, Obj *lis) - { - if (lis == lispnil) { - return FALSE; - } else if (!consp(lis)) { - /* should probably be an error of some sort */ - return FALSE; - } else if (equal(x, car(lis))) { - return TRUE; - } else { - return member(x, cdr(lis)); - } - } - - /* Return the nth element of a list. */ - - Obj * - elt(Obj *lis, int n) - { - while (n-- > 0) { - lis = cdr(lis); - } - return car(lis); - } - - Obj * - reverse(Obj *lis) - { - Obj *rslt = lispnil; - - for (; lis != lispnil; lis = cdr(lis)) { - rslt = cons(car(lis), rslt); - } - return rslt; - } - - Obj * - find_at_key(Obj *lis, char *key) - { - Obj *rest, *bdgs, *bdg; - - for_all_list(lis, rest) { - bdgs = car(rest); - bdg = car(bdgs); - if (stringp(bdg) && strcmp(key, c_string(bdg)) == 0) { - return cdr(bdgs); - } - } - return lispnil; - } - - Obj * - replace_at_key(Obj *lis, char *key, Obj *newval) - { - Obj *rest, *bdgs, *bdg; - - for_all_list(lis, rest) { - bdgs = car(rest); - bdg = car(bdgs); - if (stringp(bdg) && strcmp(key, c_string(bdg)) == 0) { - set_cdr(bdgs, newval); - return lis; - } - } - return cons(cons(new_string(key), newval), lis); - } - - /* These two routines make sure that any symbols and strings can - be read in again. */ - char * escaped_symbol(char *str) --- 2056,2059 ---- *************** *** 2112,2118 **** } - /* Note that this works correctly on NULL strings, turning them into - strings of length 0. */ - char * escaped_string(char *str) --- 2077,2080 ---- *************** *** 2133,2145 **** } - /* The escaped_string() function makes a dangerous assumption about - the length of an escaped (or even unescaped) string being less than - the BUFSIZE, which is the size of escapedthingbuf. - safe_escaped_string() is slightly less efficient, but avoids this - assumption. Do note, however, that safe_escaped_string() can result - in a memory leak, if the caller does not free the result after - using it. - */ - char * safe_escaped_string(char *str, int len) --- 2095,2098 ---- *************** *** 2170,2173 **** --- 2123,2420 ---- } + void + start_form(char *hd) + { + if (wfp) { + fprintf(wfp, "(%s", hd); + } else { + add_to_packet("("); + add_to_packet(hd); + } + } + + void + end_form(void) + { + if (wfp) { + fputs(")", wfp); + } else { + add_to_packet(")"); + } + } + + void + newline_form(void) + { + if (wfp) { + fprintf(wfp, "\n"); + } else { + add_to_packet("\n"); + } + } + + void + space_form(void) + { + if (wfp) { + fputs(" ", wfp); + } else { + add_to_packet(" "); + } + } + + void + add_to_form(char *x) + { + if (wfp) { + fprintf(wfp, " %s", x); + } else { + add_to_packet(" "); + add_to_packet(x); + } + } + + void + add_to_form_no_space(char *x) + { + if (wfp) { + fputs(x, wfp); + } else { + add_to_packet(x); + } + } + + void + add_char_to_form(int x) + { + char buf[2]; + + if (wfp) { + fprintf(wfp, "%c", x); + } else { + buf[0] = x; + buf[1] = '\0'; + add_to_packet(buf); + } + } + + void + add_num_to_form(int x) + { + char buf[30]; + + if (wfp) { + fprintf(wfp, " %d", x); + } else { + sprintf(buf, " %d", x); + add_to_packet(buf); + } + } + + void + add_num_to_form_no_space(int x) + { + char buf[30]; + + if (wfp) { + fprintf(wfp, "%d", x); + } else { + sprintf(buf, "%d", x); + add_to_packet(buf); + } + } + + void + add_num_or_dice_to_form(int x, int valtype) + { + char valbuf [BUFSIZE]; + + if (GDLDICE1 == valtype) + dice1_desc(valbuf, (DiceRep)x); + else if (GDLDICE2 == valtype) + dice2_desc(valbuf, (DiceRep)x); + else + snprintf(valbuf, BUFSIZE, "%d", x); + if (wfp) + fputs(valbuf, wfp); + else + add_to_packet(valbuf); + } + + void + add_form_to_form(Obj *x) + { + if (wfp) { + fprintlisp(wfp, x); + } else { + /* Even this might not be enough (should have a better strategy + for downloading large Lisp objects) */ + if (onemorebuf == NULL) + onemorebuf = (char *)xmalloc(50000); + sprintlisp(onemorebuf, x, 50000); + add_to_packet(onemorebuf); + } + } + + void + write_bool_prop( + char *name, + int value, + int dflt, + int nodefaulting, int addnewline) + { + if (nodefaulting || value != dflt) { + space_form(); + start_form(name); + add_to_form((char *)(value ? "true" : "false")); + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + } + + void + write_num_prop( + char *name, + int value, + int dflt, + int nodefaulting, int addnewline) + { + if (nodefaulting || value != dflt) { + space_form(); + start_form(name); + add_num_to_form(value); + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + } + + void + write_str_prop( + char *name, + char *value, + char *dflt, + int nodefaulting, int addnewline) + { + char *tmp = NULL; + int len = 0; + if (nodefaulting || string_not_default(value, dflt)) { + space_form(); + start_form(name); + if (NULL != value){ + len = strlen(value); + if (((BUFSIZE - 3) / 2) < len) { + tmp = safe_escaped_string(value, len); + add_to_form(tmp); + free(tmp); + } + else { + add_to_form(escaped_string(value)); + } + } + else { + add_to_form(escaped_string(value)); + } + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + } + + void + write_lisp_prop( + char *name, + Obj *value, + Obj *dflt, + int nodefaulting, int as_cdr, int addnewline) + { + Obj *rest; + + /* Sanity check. */ + if (value == NULL) { + run_warning("Property \"%s\" has a bad value NULL, ignoring", name); + return; + } + if (nodefaulting || !equal(value, dflt)) { + space_form(); + start_form(name); + if (as_cdr && consp(value)) { + for_all_list(value, rest) { + space_form(); + add_form_to_form(car(rest)); + } + } else { + space_form(); + add_form_to_form(value); + } + end_form(); + if (addnewline) { + newline_form(); + space_form(); + } + } + } + + #if (0) // Temp disable. + + int + member(Obj *x, Obj *lis) + { + if (lis == lispnil) { + return FALSE; + } else if (!consp(lis)) { + /* should probably be an error of some sort */ + return FALSE; + } else if (equal(x, car(lis))) { + return TRUE; + } else { + return member(x, cdr(lis)); + } + } + + /* Return the nth element of a list. */ + + Obj * + elt(Obj *lis, int n) + { + while (n-- > 0) { + lis = cdr(lis); + } + return car(lis); + } + + Obj * + reverse(Obj *lis) + { + Obj *rslt = lispnil; + + for (; lis != lispnil; lis = cdr(lis)) { + rslt = cons(car(lis), rslt); + } + return rslt; + } + + Obj * + find_at_key(Obj *lis, char *key) + { + Obj *rest, *bdgs, *bdg; + + for_all_list(lis, rest) { + bdgs = car(rest); + bdg = car(bdgs); + if (stringp(bdg) && strcmp(key, c_string(bdg)) == 0) { + return cdr(bdgs); + } + } + return lispnil; + } + #ifdef DEBUGGING Index: namer.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/namer.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** namer.cc 27 May 2006 19:28:16 -0000 1.1 --- namer.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 123,126 **** --- 123,150 ---- } + void + write_namers(void) + { + extern Obj *namerlist; + Obj *rest, *namer; + + for_all_list(namerlist, rest) { + namer = car(rest); + start_form(key(K_NAMER)); + space_form(); + add_form_to_form(namer->v.ptr.sym); + newline_form(); + space_form(); + space_form(); + add_form_to_form((Obj *) namer->v.ptr.data); + newline_form(); + space_form(); + space_form(); + end_form(); + newline_form(); + newline_form(); + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: history.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/history.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** history.cc 23 May 2006 20:59:16 -0000 1.1 --- history.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 33,38 **** --- 33,46 ---- */ + #include "gdl/base.h" + #include <cstdarg> + + #include "gdl/kernel.h" + #include "gdl/ui.h" #include "gdl/types.h" + #include "gdl/gvars.h" + #include "gdl/unit/pastunit.h" #include "gdl/history.h" + #include "gdl/score.h" NAMESPACE_XCONQ_BEGIN *************** *** 54,59 **** --- 62,330 ---- }; + // Global Variables + HistEvent *history; + // Local Variables: Behavior Options + + //! True, if events are being recorded into the history. + static int recording_events; + + // Local Function Declarations: History Management + + //! Notify side of event. + static void notify_event(Side *side, HistEvent *hevt); + + // Queries + + int + find_event_type(Obj *sym) + { + int i; + + for (i = 0; hevtdefns[i].name != NULL; ++i) { + if (strcmp(c_string(sym), hevtdefns[i].name) == 0) + return i; + } + return -1; + } + + int + pattern_matches_event(Obj *pattern, HistEvent *hevt) + { + int data0, u; + Obj *rest, *subpat; + PastUnit *pastunit; + + if (find_event_type(car(pattern)) != hevt->type) + return FALSE; + data0 = hevt->data[0]; + for_all_list(cdr(pattern), rest) { + subpat = car(rest); + if (symbolp(subpat)) { + switch (hevt->type) { + case H_UNIT_STARVED: + case H_UNIT_VANISHED: + u = utype_from_name(c_string(subpat)); + pastunit = find_past_unit(data0); + if (pastunit != NULL && pastunit->type == u) + return TRUE; + else + return FALSE; + break; + default: + return FALSE; + } + } else { + /* (should warn of bad pattern syntax?) */ + return FALSE; + } + } + return TRUE; + } + + void + event_desc_from_list(Side *side, Obj *lis, HistEvent *hevt, char *buf) + { + int n; + Obj *rest, *item; + PastUnit *pastunit; + + buf[0] = '\0'; + for_all_list(lis, rest) { + item = car(rest); + if (stringp(item)) { + strcat(buf, c_string(item)); + } else if (numberp(item)) { + n = c_number(item); + if (between(0, n, 3)) { + switch (hevt->type) { + case H_UNIT_STARVED: + case H_UNIT_VANISHED: + pastunit = find_past_unit(hevt->data[0]); + if (pastunit != NULL) { + strcat(buf, past_unit_handle(side, pastunit)); + } else { + tprintf(buf, "%d?", hevt->data[0]); + } + break; + /* (should add other event types) */ + default: + break; + } + } else { + tprintf(buf, " ??%d?? ", n); + } + } else { + strcat(buf, " ????? "); + } + } + } + + // History Management + + static + void + notify_event(Side *side, HistEvent *hevt) + { + char abuf[BUFSIZE]; + Obj *rest, *head, *pattern, *text; + Side *side2; + Unit *unit; + + for_all_list(g_event_notices(), rest) { + head = car(rest); + if (consp(head)) { + pattern = car(head); + if (symbolp(pattern) + && find_event_type(pattern) == hevt->type) { + text = cadr(head); + if (stringp(text)) { + sprintf(abuf, c_string(text)); + } else { + sprintlisp(abuf, text, 50); + } + notify(side, "%s", abuf); + return; + } else if (consp(pattern) + && symbolp(car(pattern)) + && pattern_matches_event(pattern, hevt) + ) { + text = cadr(head); + if (stringp(text)) { + strcpy(abuf, c_string(text)); + } else { + event_desc_from_list(side, text, hevt, abuf); + } + notify(side, "%s", abuf); + return; + } + } + } + /* If we didn't find anything special, still put out some generic + messages for important cases. */ + switch (hevt->type) { + case H_SIDE_LOST: + if (hevt->data[0] == side_number(side)) { + notify(side, "You lost!"); + } else { + notify(side, "%s lost!", side_desig(side_n(hevt->data[0]))); + } + break; + case H_SIDE_WON: + if (hevt->data[0] == side_number(side)) { + notify(side, "You won!"); + } else { + notify(side, "%s won!", side_desig(side_n(hevt->data[0]))); + } + break; + #if 0 /* this already has a special message */ + case H_GAME_ENDED: + notify(side, "The game is over!"); + break; + #endif + case H_UNIT_COMPLETED: + side2 = side_n(hevt->data[0]); + unit = find_unit(hevt->data[1]); + if (unit != NULL) { + if (side2 == side) { + notify(side, "You completed %s.", + unit_handle(side, unit)); + } else { + notify(side, "%s completed %s.", + side_desig(side2), unit_handle(side2, unit)); + } + } + break; + case H_UNIT_CREATED: + side2 = side_n(hevt->data[0]); + unit = find_unit(hevt->data[1]); + if (unit != NULL) { + if (side2 == side) { + notify(side, "You created %s.", + unit_handle(side, unit)); + } else { + notify(side, "%s created %s.", + side_desig(side2), unit_handle(side2, unit)); + } + } + break; + default: + break; + } + } + + HistEvent * + record_event(HistEventType type, SideMask observers, ...) + { + int i, val; + char *descs; + HistEvent *hevt; + Side *side; + va_list ap; + + if (!recording_events) + return NULL; + hevt = create_historical_event(type); + hevt->startdate = g_turn(); + hevt->enddate = g_turn(); + hevt->observers = observers; + descs = hevtdefns[type].datadescs; + + va_start(ap, observers); + for (i = 0; descs[i] != '\0'; ++i) { + if (i >= 4) + run_error("hevt type %d has too many parameters", type); + val = va_arg(ap, int); + hevt->data[i] = val; + } + va_end(ap); + + /* Check on plausibility of event data. */ + for (i = 0; descs[i] != '\0'; ++i) { + val = hevt->data[i]; + switch (descs[i]) { + case 'S': + if (!between(0, val, numsides)) + run_warning("invalid side number %d in hist event", val); + break; + case 'U': + /* Note that when validating unit id, the unit may be in + the middle of the the process of becoming a past unit, + so allowing finding a dead unit. */ + if (val != 0 + && find_unit_dead_or_alive(val) == NULL + && find_past_unit(val) == NULL) + run_warning("invalid unit/pastunit id %d in hist event", val); + break; + default: + break; + } + } + /* Insert the newly created event. */ + hevt->next = history; + hevt->prev = history->prev; + history->prev->next = hevt; + history->prev = hevt; + Dprintf("Recorded event %s (observed by %d)\n", + hevtdefns[hevt->type].name, hevt->observers); + if (observers != NOSIDES) { + /* Let all the observers' interfaces look at this event. */ + for_all_sides(side) { + if (side_in_set(side, observers) && active_display(side)) { + update_event_display(side, hevt, TRUE); + notify_event(side, hevt); + if (g_event_movies() != lispnil) { + play_event_movies(side, hevt); + } + } + } + } + /* Flag that we should look at post-event scorekeepers soon. */ + if (any_post_event_scores && !beforestart && !endofgame) + need_post_event_scores = TRUE; + return hevt; + } + // Lifecycle Management *************** *** 136,139 **** --- 407,468 ---- } + void + write_historical_event(HistEvent *hevt) + { + int i; + char *descs; + + /* Might be reasons not to write this event. */ + if (hevt->startdate < 0) + return; + start_form(key(K_EVT)); + add_num_to_form(hevt->startdate); + add_to_form(hevtdefns[hevt->type].name); + if (hevt->observers == ALLSIDES) + add_to_form(key(K_ALL)); + else + add_num_to_form(hevt->observers); + descs = hevtdefns[hevt->type].datadescs; + for (i = 0; descs[i] != '\0'; ++i) { + switch (descs[i]) { + case 'm': + case 'n': + case 's': + case 'S': + case 'u': + case 'U': + case 'x': + case 'y': + add_num_to_form(hevt->data[i]); + break; + default: + run_warning("'%c' is not a recognized history data desc char", + descs[i]); + break; + } + } + end_form(); + newline_form(); + } + + void + write_history(void) + { + PastUnit *pastunit; + HistEvent *hevt; + + /* Write all the past units that might be mentioned in events. These + should already be sorted by id. */ + for (pastunit = past_unit_list; pastunit != NULL; pastunit = pastunit->next) + write_past_unit(pastunit); + newline_form(); + /* Now write all the events, doing the first one separately so as to + simplify testing for the end of the history list (which is circular). */ + write_historical_event(history); + for (hevt = history->next; hevt != history; hevt = hevt->next) + write_historical_event(hevt); + newline_form(); + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: module.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/module.cc,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** module.cc 30 May 2006 02:51:07 -0000 1.3 --- module.cc 2 Jun 2006 16:57:43 -0000 1.4 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2004-2006 Eric A. McDonald --- 6,10 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1897-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2004-2006 Eric A. McDonald *************** *** 59,62 **** --- 59,66 ---- Module *curmodule; + FILE *wfp; + + Module *reshaper; + // Global Variables: Validation *************** *** 73,76 **** --- 77,85 ---- PackedBoolTable *G_advances_synopsis = NULL; + // Global Variables: Buffers + + //! Buffer for shortest names. + char *shortestbuf; + // Local Variables *************** *** 78,81 **** --- 87,100 ---- static Module *mainmodule; + //! Module for capturing snapshot of game state. + /*! + A pre-allocated module used for when we're saving the game and may + not do any more allocation. + */ + static Module *spare_module; + + //! Name of spare module file. + static char *spare_file_name; + // Local Variables: Behavior Options *************** *** 182,185 **** --- 201,207 ---- static void end_conditional(Obj *form, Module *module); + //! Serialize variants to GDL. + static void write_variants(Variant *varray); + // Notifications *************** *** 1810,1813 **** --- 1832,2066 ---- } + void + init_write(void) + { + spare_module = create_game_module("spare module"); + shortestbuf = (char *) xmalloc(BUFSIZE); + spare_file_name = (char *) xmalloc(PATH_SIZE); + } + + static + void + write_variants(Variant *varray) + { + int i; + Obj *rest; + Variant *var; + + for (i = 0; varray[i].id != lispnil; ++i) { + var = &(varray[i]); + space_form(); + start_form(""); + /* Write the variant's string name if different from symbol. */ + if (!empty_string(var->name) + && !(symbolp(var->id) + && strcmp(var->name, c_string(var->id)) == 0)) { + add_to_form(escaped_string(var->name)); + space_form(); + } + add_form_to_form(var->id); + if (var->dflt != lispnil) { + space_form(); + add_form_to_form(var->dflt); + } + for_all_list(var->cases, rest) { + space_form(); + add_form_to_form(car(rest)); + } + end_form(); + } + } + + int + reshape_the_output(Module *module) + { + return (module->maybe_reshape + && (module->subarea_width != area.width + || module->subarea_height != area.height + || module->subarea_x != 0 + || module->subarea_y != 0 + || module->final_subarea_width != area.width + || module->final_subarea_height != area.height + || module->final_subarea_x != 0 + || module->final_subarea_y != 0 + || module->final_width != area.width + || module->final_height != area.height + || module->final_circumference != world.circumference)); + } + + int + write_game_module(Module *module, char *fname) + { + if (module->filename == NULL && tmprid == 0) { + /* (should be an error?) */ + return FALSE; + } + if (module->filename && fname) { + wfp = open_file(fname, "w"); + } else { + wfp = NULL; + } + if (wfp != NULL || tmprid > 0) { + /* Write the definition of this game module. */ + start_form(key(K_GAME_MODULE)); + add_to_form(escaped_string(module->name)); + newline_form(); + space_form(); + if (module->def_all) { + write_str_prop(key(K_TITLE), module->title, + "", FALSE, TRUE); + write_lisp_prop(key(K_BLURB), module->blurb, + lispnil, FALSE, FALSE, TRUE); + write_str_prop(key(K_PICTURE_NAME), module->picturename, + "", FALSE, TRUE); + write_str_prop(key(K_BASE_MODULE), module->basemodulename, + "", FALSE, TRUE); + write_str_prop(key(K_DEFAULT_BASE_MODULE), module->defaultbasemodulename, + "", FALSE, TRUE); + write_str_prop(key(K_BASE_GAME), module->basegame, + "", FALSE, TRUE); + write_str_prop(key(K_FILENAME), module->filename, + "", FALSE, TRUE); + write_str_prop(key(K_VERSION), module->version, + "", FALSE, TRUE); + if (module->variants) { + space_form(); + start_form(key(K_VARIANTS)); + write_variants(module->variants); + end_form(); + newline_form(); + } + write_str_prop(key(K_ORIGINAL_MODULE), module->origmodulename, + "", FALSE, TRUE); + if (module->origvariants) { + space_form(); + start_form(key(K_ORIGINAL_VARIANTS)); + write_variants(module->origvariants); + end_form(); + newline_form(); + } + } + space_form(); + end_form(); + newline_form(); + newline_form(); + if (module->def_all || module->def_types) + write_types(); + if (module->def_all || module->def_tables) + write_tables(module->compress_tables); + if (module->def_all || module->def_globals) + write_globals(); + if (module->def_all || module->def_scoring) + write_scorekeepers(); + doreshape = reshape_the_output(module); + reshaper = module; + if (module->def_all || module->def_world) + write_world(); + if (module->def_all || module->def_areas) + write_areas(module); + if (module->def_all || module->def_sides) + write_doctrines(); + if (module->def_all || module->def_sides) + write_sides(module); + if (module->def_all || module->def_players) + write_players(); + #if 0 + if (module->def_all || module->def_agreements) + write_agreements(); + #endif + if (module->def_all || module->def_units) + write_units(module); + if (module->def_all || module->def_history) + write_history(); + if (module->def_all) + write_namers(); + if (module->def_all) + write_images(); + /* Write the game notes here (seems reasonable, no deeper reason). */ + if (module->instructions != lispnil) { + start_form(key(K_GAME_MODULE)); + space_form(); + write_lisp_prop(key(K_INSTRUCTIONS), module->instructions, + lispnil, FALSE, FALSE, TRUE); + newline_form(); + space_form(); + space_form(); + end_form(); + newline_form(); + newline_form(); + } + if (module->notes != lispnil) { + start_form(key(K_GAME_MODULE)); + space_form(); + write_lisp_prop(key(K_NOTES), module->notes, + lispnil, FALSE, FALSE, TRUE); + newline_form(); + space_form(); + space_form(); + end_form(); + newline_form(); + newline_form(); + } + if (module->designnotes != lispnil) { + start_form(key(K_GAME_MODULE)); + space_form(); + write_lisp_prop(key(K_DESIGN_NOTES), module->designnotes, + lispnil, FALSE, FALSE, TRUE); + newline_form(); + space_form(); + space_form(); + end_form(); + newline_form(); + newline_form(); + } + if (wfp != NULL) + fclose(wfp); + else + flush_write(); + return TRUE; + } else { + return FALSE; + } + } + + int + write_entire_game_state(char *fname) + { + Module *module; + int rslt; + + /* Record the attempt to save state. Do it before actually saving, + so that it appears in the saved history. */ + if (!memory_exhausted && !debugging_state_sync) + record_event(H_GAME_SAVED, ALLSIDES); + /* No additional allocation should ever happen during saving, + so complain if it does. */ + xmalloc_warnings = TRUE; + module = spare_module; + copy_module(module, mainmodule); + module->name = mainmodule->name; + module->filename = find_name(fname); + module->version = NULL; + module->variants = NULL; + /* We write all types etc, so suppress base module load attempts. */ + module->basemodulename = NULL; + module->defaultbasemodulename = NULL; + module->compress_tables = TRUE; + module->compress_layers = TRUE; + module->def_all = TRUE; + rslt = write_game_module(module, fname); + xmalloc_warnings = FALSE; + /* Record that the game's state is accurately saved away. */ + if (rslt) { + gamestatesafe = TRUE; + if (!memory_exhausted && !debugging_state_sync) { + /* Report success to the users. We can't use notify_event + because we want to report the filename. */ + notify_all("Game was saved to \"%s\".", fname); + } + } + return rslt; + } + #if (0) // Temp disable. *************** *** 1890,1912 **** } - /* This is true if any actual reshaping is required. */ - - int - reshape_the_output(Module *module) - { - return (module->maybe_reshape - && (module->subarea_width != area.width - || module->subarea_height != area.height - || module->subarea_x != 0 - || module->subarea_y != 0 - || module->final_subarea_width != area.width - || module->final_subarea_height != area.height - || module->final_subarea_x != 0 - || module->final_subarea_y != 0 - || module->final_width != area.width - || module->final_height != area.height - || module->final_circumference != world.circumference)); - } - /* Check if the proposed reshape will actually work. */ --- 2143,2146 ---- Index: tables.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/tables.cc,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** tables.cc 28 May 2006 22:31:21 -0000 1.4 --- tables.cc 2 Jun 2006 16:57:43 -0000 1.5 *************** *** 6,12 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2004-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1987-1989 Stanley T. Shebs Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2005-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 90,93 **** --- 90,98 ---- NAMESPACE_GDL_BEGIN + // Local Data Structures + + //! Simple histogram struct - count and value, that's all. + struct histo { int count, val; }; + // Globals *************** *** 165,168 **** --- 170,176 ---- Obj *indexes1, Obj *indexes2, Obj *values); + //! Sort predicate - *descending* order by count. + static int histo_compare(const void *x, const void *y); + // Table Accessors *************** *** 489,492 **** --- 497,764 ---- } + static + int + histo_compare(const void *x, const void *y) + { + return ((struct histo *) y)->count - ((struct histo *) x)->count; + } + + #if (0) + void + write_type_value_list( + int typ, int *flags, int dim, int (*getter)(int, int), int i) + { + int j, first = TRUE, listlen = 0; + + for (j = 0; j < dim; ++j) + if (flags == NULL || flags[j]) + ++listlen; + if (listlen > 1) + start_form(""); + for (j = 0; j < dim; ++j) { + if (flags == NULL || flags[j]) { + if (first) + first = FALSE; + else + space_form(); + add_num_to_form_no_space((*getter)(i, j)); + } + } + if (listlen > 1) + end_form(); + } + #endif + + void + write_table(char *name, int (*getter)(int, int), int dflt, int typ1, int typ2, + int valtype, int compress) + { + int i, j, k, colvalue, constcol, next; + int numrandoms, nextrowdiffers, writeconst; + int sawfirst, constrands, constval; + int dim1 = numtypes_from_index_type(typ1); + int dim2 = numtypes_from_index_type(typ2); + struct histo mostcommon[500]; /* more than max of num[utma]types */ + int indexes1[500], randoms[500]; + + start_form(key(K_TABLE)); + add_to_form(name); + add_to_form(" ;"); + add_num_or_dice_to_form(dflt, valtype); + if (!compress) { + /* Write every value separately. */ + for (i = 0; i < dim1; ++i) { + newline_form(); + space_form(); + space_form(); + start_form(escaped_symbol(name_from_typ(typ1, i))); + add_to_form((char *)star_from_typ(typ2)); + space_form(); + start_form(""); + for (j = 0; j < dim2; ++j) { + add_num_or_dice_to_form((*getter)(i, j), valtype); + } + end_form(); + end_form(); + } + } else if (dim1 <= dim2) { + /* Analyze the table by rows. */ + for (k = 0; k < dim1; ++k) + indexes1[k] = FALSE; + for (i = 0; i < dim1; ++i) { + /* First see if this row has all the same values as the next. */ + indexes1[i] = TRUE; + nextrowdiffers = FALSE; + if (i < dim1 - 1) { + for (j = 0; j < dim2; ++j) { + if ((*getter)(i, j) != (*getter)(i + 1, j)) { + nextrowdiffers = TRUE; + break; + } + } + } else { + /* The last row is *always* "different". */ + nextrowdiffers = TRUE; + } + /* (should look at *all* rows to find matching rows before + dumping one) */ + if (nextrowdiffers) { + /* Make a histogram of all the values in this row. */ + mostcommon[0].count = 1; + mostcommon[0].val = (*getter)(i, 0); + next = 1; + for (j = 0; j < dim2; ++j) { + for (k = 0; k < next; ++k) { + if (mostcommon[k].val == (*getter)(i, j)) { + ++(mostcommon[k].count); + break; + } + } + if (k == next) { + mostcommon[next].count = 1; + mostcommon[next].val = (*getter)(i, j); + ++next; + } + } + if (next == 1 && mostcommon[0].val == dflt) { + /* Entire row(s) is/are just the default table value. */ + } else { + writeconst = FALSE; + numrandoms = 0; + if (next == 1) { + /* Only one value in the row(s). */ + writeconst = TRUE; + } else { + qsort(mostcommon, next, sizeof(struct histo), + histo_compare); + if (mostcommon[0].count >= (3 * dim2) / 4) { + /* The most common value in this row(s) is + not the only value, but it is worth + writing into a separate clause. */ + writeconst = TRUE; + for (j = 0; j < dim2; ++j) { + /* Flag the other values as needing to be + written separately. */ + randoms[j] = + (mostcommon[0].val != (*getter)(i, j)); + if (randoms[j]) + ++numrandoms; + } + } else { + /* Flag all in the row as randoms. */ + for (j = 0; j < dim2; ++j) { + randoms[j] = TRUE; + ++numrandoms; + } + } + } + /* Write out the most common value (if + non-default) in the row(s), expressing it with + a clause that applies the value to the entire + row(s). */ + if (writeconst && mostcommon[0].val != dflt) { + newline_form(); + space_form(); + space_form(); + start_form(""); + write_type_name_list(typ1, indexes1, dim1); + add_to_form((char *)star_from_typ(typ2)); + add_num_or_dice_to_form(mostcommon[0].val, valtype); + end_form(); + } + /* Now override the most common value with any + exceptions. */ + if (numrandoms > 0) { + constrands = TRUE; + sawfirst = FALSE; + for (j = 0; j < dim2; ++j) { + if (randoms[j]) { + if (!sawfirst) { + constval = (*getter)(i, j); + sawfirst = TRUE; + } + if (sawfirst && constval != (*getter)(i, j)) { + constrands = FALSE; + break; + } + } + } + if (constrands) { + newline_form(); + space_form(); + space_form(); + start_form(""); + write_type_name_list(typ1, indexes1, dim1); + space_form(); + write_type_name_list(typ2, randoms, dim2); + add_num_or_dice_to_form(constval, valtype); + end_form(); + } else { + /* We have a group of rows with varying data + in the columns; write a separate row. */ + for (j = 0; j < dim2; ++j) { + if (randoms[j]) { + newline_form(); + space_form(); + space_form(); + start_form(""); + write_type_name_list(typ1, indexes1, dim1); + add_to_form(escaped_symbol(name_from_typ(typ2, j))); + add_num_or_dice_to_form((*getter)(i, j), valtype); + end_form(); + } + } + } + } + } + /* Reset the row flags in preparation for the next group + of rows whose contents match each other. */ + for (k = 0; k < dim1; ++k) + indexes1[k] = FALSE; + } + } + } else { + /* Analyze the table by columns. */ + /* Don't work as hard to optimize; this case should be uncommon, + since there are usually more types of units than + materials or terrain. */ + for (j = 0; j < dim2; ++j) { + constcol = TRUE; + colvalue = (*getter)(0, j); + for (i = 0; i < dim1; ++i) { + if ((*getter)(i, j) != colvalue) { + constcol = FALSE; + break; + } + } + if (!constcol || colvalue != dflt) { + newline_form(); + space_form(); + space_form(); + start_form((char *)star_from_typ(typ1)); + add_to_form(escaped_symbol(name_from_typ(typ2, j))); + /* Write out either a single constant value or a list of + varying values, as appropriate. */ + if (constcol) { + add_num_or_dice_to_form(colvalue, valtype); + } else { + space_form(); + start_form(""); + for (i = 0; i < dim1; ++i) { + add_num_or_dice_to_form((*getter)(i, j), valtype); + } + end_form(); + } + end_form(); + } + } + } + newline_form(); + space_form(); + space_form(); + end_form(); + newline_form(); + } + + void + write_tables(int compress) + { + int tbl; + + newline_form(); + for (tbl = 0; tabledefns[tbl].name != 0; ++tbl) { + /* Don't write out tables used internally only, unless debugging. */ + if ((strncmp(tabledefns[tbl].name, "zz-", 3) == 0) && !Debug) + continue; + if (*(tabledefns[tbl].table) != NULL) { + write_table(tabledefns[tbl].name, + tabledefns[tbl].getter, tabledefns[tbl].dflt, + tabledefns[tbl].index1, tabledefns[tbl].index2, + tabledefns[tbl].valtype, compress); + newline_form(); + } + } + } + NAMESPACE_GDL_END NAMESPACE_XCONQ_END Index: Makefile.am =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/Makefile.am,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** Makefile.am 29 May 2006 20:11:12 -0000 1.8 --- Makefile.am 2 Jun 2006 16:57:43 -0000 1.9 *************** *** 11,18 **** libconq_gdl_la_SOURCES += dir.cc namer.cc pact.cc history.cc libconq_gdl_la_SOURCES += player.cc score.cc world.cc module.cc - libconq_gdl_la_SOURCES += write.cc ! libconq_gdl_la_LIBADD = unit/libconq_gdl_media.la libconq_gdl_la_LIBADD += unit/libconq_gdl_unit.la libconq_gdl_la_LIBADD += side/libconq_gdl_side.la ! libconq_gdl_la_LIBADD += side/libconq_gdl_gamearea.la --- 11,17 ---- libconq_gdl_la_SOURCES += dir.cc namer.cc pact.cc history.cc libconq_gdl_la_SOURCES += player.cc score.cc world.cc module.cc ! libconq_gdl_la_LIBADD = media/libconq_gdl_media.la libconq_gdl_la_LIBADD += unit/libconq_gdl_unit.la libconq_gdl_la_LIBADD += side/libconq_gdl_side.la ! libconq_gdl_la_LIBADD += gamearea/libconq_gdl_gamearea.la Index: score.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/score.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** score.cc 28 May 2006 18:10:41 -0000 1.1 --- score.cc 2 Jun 2006 16:57:43 -0000 1.2 *************** *** 56,59 **** --- 56,63 ---- Scorekeeper *scorekeepers; int numscorekeepers; + int numscores; + + int any_post_action_scores; + int any_post_event... [truncated message content] |
From: Eric M. <eri...@us...> - 2006-05-30 02:51:12
|
Update of /cvsroot/xconq/xconq/src/gdl In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv14484 Modified Files: module.cc Log Message: Fix includes. Index: module.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/module.cc,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** module.cc 29 May 2006 20:11:12 -0000 1.2 --- module.cc 30 May 2006 02:51:07 -0000 1.3 *************** *** 40,43 **** --- 40,44 ---- #include "gdl/media/imf.h" #include "gdl/unit/unit.h" + #include "gdl/unit/pastunit.h" #include "gdl/unit/unitview.h" #include "gdl/side/side.h" |
From: Eric M. <eri...@us...> - 2006-05-30 02:50:23
|
Update of /cvsroot/xconq/xconq/src/include/gdl In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv14143 Modified Files: kernel.h ui.h Log Message: Update forward decls for kernel and UI. Index: ui.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/ui.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ui.h 15 May 2006 00:08:16 -0000 1.1 --- ui.h 30 May 2006 02:50:19 -0000 1.2 *************** *** 34,38 **** #define XCONQ_GDL_UI_H ! #include "gdl/base.h" NAMESPACE_XCONQ_BEGIN --- 34,55 ---- #define XCONQ_GDL_UI_H ! #include "gdl/lisp.h" ! #include "gdl/unit/unit_FWD.h" ! #include "gdl/side/side_FWD.h" ! ! // Global Constants: Display Updates ! ! //! Display Update: always ! #define UPDATE_ALWAYS 1 ! //! Display Update: adjacent ! #define UPDATE_ADJ 2 ! //! Display Update: cover ! #define UPDATE_COVER 4 ! //! Display Update: termperature ! #define UPDATE_TEMP 8 ! //! Display Update: clouds ! #define UPDATE_CLOUDS 16 ! //! Display Update: winds ! #define UPDATE_WINDS 32 NAMESPACE_XCONQ_BEGIN *************** *** 41,44 **** --- 58,64 ---- // Global Functions: Notification + //! Notify given side of something via UI. + extern void notify(Side *side, char *str, ...); + //! Announce amount of progress in reading a GDL form. extern void announce_read_progress(void); *************** *** 52,57 **** extern void end_printing_forms(void); NAMESPACE_GDL_END NAMESPACE_XCONQ_END ! #endif // ifndef XCONQ_GDL_UI_H \ No newline at end of file --- 72,86 ---- extern void end_printing_forms(void); + // Global Functions: Status Displays + + //! Ask UI to update display of given unit. + extern void update_unit_display(Side *side, Unit *unit, int rightnow); + //! Ask UI to update display of given cell. + extern void update_cell_display(Side *side, int x, int y, int flags); + //! Flush display buffers for given side. + extern void flush_display_buffers(Side *side); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END ! #endif // ifndef XCONQ_GDL_UI_H Index: kernel.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/kernel.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** kernel.h 15 May 2006 00:08:16 -0000 1.1 --- kernel.h 30 May 2006 02:50:19 -0000 1.2 *************** *** 34,38 **** #define XCONQ_GDL_KERNEL_H ! #include "gdl/base.h" NAMESPACE_XCONQ_BEGIN --- 34,38 ---- #define XCONQ_GDL_KERNEL_H ! #include "gdl/lisp.h" NAMESPACE_XCONQ_BEGIN *************** *** 44,47 **** --- 44,52 ---- extern int numremotes; + // Global Variables: Game State + + //! True, if at end of game. + extern int endofgame; + // Global Variables: Notification *************** *** 57,59 **** NAMESPACE_XCONQ_END ! #endif // ifndef XCONQ_GDL_KERNEL_H \ No newline at end of file --- 62,64 ---- NAMESPACE_XCONQ_END ! #endif // ifndef XCONQ_GDL_KERNEL_H |
From: Eric M. <eri...@us...> - 2006-05-30 02:49:10
|
Update of /cvsroot/xconq/xconq/src/include/gdl/media In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv13792/d/include/gdl/media Modified Files: imf.h img.h Log Message: Finish adding GDL deserialization support for GDL image families. Index: imf.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/media/imf.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** imf.h 15 May 2006 03:41:10 -0000 1.1 --- imf.h 30 May 2006 02:49:03 -0000 1.2 *************** *** 1,4 **** // xConq ! // GDL image family lifecycle management and serialization/deserialization. // $Id$ --- 1,4 ---- // xConq ! // Lifecycle management and ser/deser for GDL image families. // $Id$ *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1992-2000 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald --- 6,11 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs ! Copyright (C) 1991-2000 Stanley T. Shebs Copyright (C) 2005-2006 Eric A. McDonald *************** *** 28,32 **** /*! \file ! \brief GDL image family lifecycle management and serialization/deserialization. \ingroup grp_gdl */ --- 29,33 ---- /*! \file ! \brief Lifecycle management and ser/deser for GDL image families. \ingroup grp_gdl */ *************** *** 37,40 **** --- 38,45 ---- #include "gdl/media/img.h" + //! Maximum number of image families to allocate. + /*! \todo Should remove these fixed limits. */ + #define MAXIMAGEFAMILIES 3000 + NAMESPACE_XCONQ_BEGIN NAMESPACE_GDL_BEGIN *************** *** 96,99 **** --- 101,128 ---- //! Find image family, if it exists, from given name. extern ImageFamily *find_imf(char *name); + //! Given name, find or create image family with that name. + extern ImageFamily *get_imf(char *name); + + // Validation + + //! Check if given name is valid for image family. + extern int valid_imf_name(char *name); + + // Image Preparation + + //! Compute regions of interest in image data. + extern void compute_image_bboxes(ImageFamily *imf); + + // GDL I/O + + //! Read GDL form into GDL image family. + /*! + Interpret the image family definition as a list of images and/or a + notes property. + */ + extern void interp_imf_contents(ImageFamily *imf, Obj *form); + + //! Read GDL image family from GDL form. + extern ImageFamily *interp_imf(Obj *form); NAMESPACE_GDL_END Index: img.h =================================================================== RCS file: /cvsroot/xconq/xconq/src/include/gdl/media/img.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** img.h 15 May 2006 03:41:10 -0000 1.1 --- img.h 30 May 2006 02:49:03 -0000 1.2 *************** *** 1,4 **** // xConq ! // Lifecycle management and serialization/deserialization of GDL images. // $Id$ --- 1,4 ---- // xConq ! // Lifecycle management and ser/deser of GDL images. // $Id$ *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs ! Copyright (C) 1991-2000 Stanley T. Shebs ! Copyright (C) 2005-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 27,31 **** /*! \file ! \brief Lifecycle management and serialization/deserialization of GDL images. \ingroup grp_gdl */ --- 29,33 ---- /*! \file ! \brief Lifecycle management and ser/deser of GDL images. \ingroup grp_gdl */ *************** *** 36,39 **** --- 38,55 ---- #include "gdl/lisp.h" + // Function Macros + + //! How many bytes per row in image data? + #define computed_rowbytes(w, pixelsize) (((w * pixelsize) + 7) / 8) + + //! Convert hexadecimal digit to decimal number. + #define hextoi(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10)) + + // Iterator Macros + + //! Iterate over all images in GDL image family. + #define for_all_images(imf,img) \ + for ((img) = (imf)->images; (img) != NULL; (img) = (img)->next) + NAMESPACE_XCONQ_BEGIN NAMESPACE_GDL_BEGIN *************** *** 167,170 **** --- 183,213 ---- } Image; + // Global Variables: Behavior Modifiers + + //! Flag that indicates limited GDI memory in certain versions of Windows. + extern short poor_memory; + + // Queries + + //! Get or create image of given specs from given image family. + extern Image *get_img(struct a_image_family *imf, int w, int h); + + // Image Preparation + + //! Compute region of interest in GDL image data. + extern void compute_image_bbox(Image *img); + + // GDL I/O + + //! Read GDL image from GDL forms. + /*! + Given an image family, a size, and a list describing the elements + of a single image, parse the size and elements, put those into the + right slots of an image object. Also detect and warn about changes + to an existing image, since this usually indicates some kind of + problem. + */ + extern void interp_image(struct a_image_family *imf, Obj *size, Obj *parts); + NAMESPACE_GDL_END NAMESPACE_XCONQ_END |
From: Eric M. <eri...@us...> - 2006-05-30 02:49:09
|
Update of /cvsroot/xconq/xconq/src/gdl/media In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv13792/d/gdl/media Modified Files: imf.cc img.cc Log Message: Finish adding GDL deserialization support for GDL image families. Index: imf.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/media/imf.cc,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** imf.cc 15 May 2006 03:37:24 -0000 1.2 --- imf.cc 30 May 2006 02:49:02 -0000 1.3 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs ! Copyright (C) 1991-2001 Stanley T. Shebs ! Copyright (C) 2005-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 41,44 **** --- 43,51 ---- int numimages = 0; + // Local Function Declarations: Lifecycle Management + + //! Create new image family. + static ImageFamily *new_imf(char *name); + // Queries *************** *** 55,58 **** } NAMESPACE_GDL_END ! NAMESPACE_XCONQ_END \ No newline at end of file --- 62,185 ---- } + ImageFamily * + get_imf(char *name) + { + ImageFamily *imf = NULL; + + if (name == NULL) { + init_warning("can't get an unnamed image family"); + return NULL; + } + if (!valid_imf_name(name)) { + init_warning("\"%s\" is not a valid image family name", name); + return NULL; + } + if (images == NULL) { + images = + (ImageFamily **) xmalloc(MAXIMAGEFAMILIES * sizeof(ImageFamily *)); + } + imf = find_imf(name); + if (imf == NULL) { + if (numimages >= MAXIMAGEFAMILIES) { + init_warning("MAXIMAGEFAMILIES exceeded, skipping image family %s", name); + return NULL; + } + imf = new_imf(copy_string(name)); + if (imf != NULL) { + images[numimages++] = imf; + } + } + return imf; + } + + // Validation + + int + valid_imf_name(char *name) + { + char *tmp; + + for (tmp = name; *tmp; ++tmp) { + if (!(isalnum(*tmp) + || (tmp != name && *tmp == '-'))) + return FALSE; + } + return TRUE; + } + + // Image Preparation + + void + compute_image_bboxes(ImageFamily *imf) + { + Image *img; + + if (imf == NULL) + return; + for_all_images(imf, img) { + compute_image_bbox(img); + } + } + + // Lifecycle Management + + static + ImageFamily * + new_imf(char *name) + { + ImageFamily *imf; + + imf = (ImageFamily *) xmalloc(sizeof(ImageFamily)); + imf->name = name; + imf->notes = lispnil; + return imf; + } + + // GDL I/O + + ImageFamily * + interp_imf(Obj *form) + { + ImageFamily *imf; + + if (stringp(cadr(form))) { + imf = get_imf(c_string(cadr(form))); + if (imf != NULL) { + interp_imf_contents(imf, cddr(form)); + } + return imf; + } else { + run_warning("image family name must be a string"); + } + return NULL; + } + + void + interp_imf_contents(ImageFamily *imf, Obj *clauses) + { + Obj *rest, *clause; + + for_all_list(clauses, rest) { + clause = car(rest); + if (consp(clause)) { + if (symbolp(car(clause))) { + if (match_keyword(car(clause), K_NOTES)) { + imf->notes = cadr(clause); + syntax_error(clause, "extra junk after property value"); + } else { + syntax_error(clause, "unknown image family property"); + } + } else if (consp(car(clause))) { + interp_image(imf, car(clause), cdr(clause)); + } else { + syntax_error(clause, "not image or image family property"); + } + } else { + syntax_error(clause, "bogus clause"); + } + } + compute_image_bboxes(imf); + } + NAMESPACE_GDL_END ! NAMESPACE_XCONQ_END Index: img.cc =================================================================== RCS file: /cvsroot/xconq/xconq/src/gdl/media/img.cc,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** img.cc 15 May 2006 02:08:49 -0000 1.1 --- img.cc 30 May 2006 02:49:02 -0000 1.2 *************** *** 6,10 **** /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// --- 6,12 ---- /*//////////////////////////// COPYRIGHT NOTICE //////////////////////////////// ! Copyright (C) 1989 Stanley T. Shebs ! Copyright (C) 1991-2001 Stanley T. Shebs ! Copyright (C) 2005-2006 Eric A. McDonald //////////////////////////////////// LICENSE /////////////////////////////////// *************** *** 31,40 **** */ ! #include "gdl/media/img.h" NAMESPACE_XCONQ_BEGIN NAMESPACE_GDL_BEGIN NAMESPACE_GDL_END --- 33,349 ---- */ ! #include "gdl/media/imf.h" NAMESPACE_XCONQ_BEGIN NAMESPACE_GDL_BEGIN + // Local Enumerations: Image Layer Types + + enum { + K_MONO_, + K_MASK_, + K_COLR_, + K_FILE_, + K_OTHER_ + }; + + // Global Variables: Behavior Modifiers + + short poor_memory = FALSE; + + // Local Function Delcarations: Queries + + //! Get an image of given size from given family. + /*! Create new image, if necessary. */ + static Image *get_subimg(ImageFamily *imf, int w, int h); + + // Queries + + Image * + get_subimg(ImageFamily *imf, int w, int h) + { + Image *nimg; + /* Not found; create a new image and add it to the family. */ + nimg = (Image *) xmalloc(sizeof(Image)); + nimg->w = w; nimg->h = h; + nimg->embedx = nimg->embedy = -1; + nimg->embedw = nimg->embedh = -1; + nimg->monodata = nimg->colrdata = nimg->maskdata = lispnil; + nimg->filedata = lispnil; + nimg->palette = lispnil; + nimg->actualw = w; nimg->actualh = h; + nimg->notes = lispnil; + nimg->bboxw = w; nimg->bboxh = h; + return nimg; + } + + Image * + get_img(ImageFamily *imf, int w, int h) + { + Image *img, *nimg, *previmg; + + for_all_images(imf, img) { + if (w == img->w && h == img->h) + return img; + } + /* Not found; create a new image and add it to the family. */ + nimg = (Image *) xmalloc(sizeof(Image)); + nimg->w = w; nimg->h = h; + nimg->embedx = nimg->embedy = -1; + nimg->embedw = nimg->embedh = -1; + nimg->monodata = nimg->colrdata = nimg->maskdata = lispnil; + nimg->filedata = lispnil; + nimg->palette = lispnil; + nimg->actualw = w; nimg->actualh = h; + nimg->notes = lispnil; + nimg->bboxw = w; nimg->bboxh = h; + /* Rely on zeroing of xmalloc blocks to avoid clearing other fields. */ + /* Link in order by size, smallest first. */ + previmg = NULL; + for_all_images(imf, img) { + if ((nimg->w < img->w) + || (nimg->w == img->w && nimg->h < img->h)) + break; + previmg = img; + } + if (previmg != NULL) { + nimg->next = previmg->next; + previmg->next = nimg; + } else { + nimg->next = imf->images; + imf->images = nimg; + } + ++(imf->numsizes); + return nimg; + } + + // Image Preparation + + void + compute_image_bbox(Image *img) + { + int numbytes, i, j = 0, byte, x, y, x1, x2, k; + int xmin, ymin, xmax, ymax; + char *data = NULL; + Obj *datalist, *next; + + datalist = img->maskdata; + numbytes = img->h * computed_rowbytes(img->w, 1); + x = y = 0; + xmin = img->w; ymin = img->h; + xmax = 0; ymax = 0; + for (i = 0; i < numbytes; ++i) { + if (img->maskdata != lispnil) { + if (data == NULL || data[j] == '\0') { + next = car(datalist); + if (!stringp(next)) { + syntax_error(datalist, "garbage in image data list"); + return; + } + data = c_string(next); + j = 0; + datalist = cdr(datalist); + } + /* Just skip over slashes, which are for readability only. */ + if (data[j] == '/') + ++j; + byte = hextoi(data[j]) * 16 + hextoi(data[j+1]); + j += 2; + } else if (img->rawmaskdata != NULL) { + byte = img->rawmaskdata[i] & 0xff; + } else { + byte = 0xff; + } + if (byte != 0) { + /* Find the most-significant and least-significant bits in + the mask byte. */ + x1 = x2 = -1; + k = 0; + while (byte != 0) { + if ((byte & 0x1) != 0 && x2 < 0) + x2 = x + 7 - k; + byte >>= 1; + if (byte == 0 && x1 < 0) + x1 = x + 7 - k; + ++k; + } + xmin = min(x1, xmin); ymin = min(y, ymin); + xmax = max(x2, xmax); ymax = max(y, ymax); + } + x += 8; + if (x >= img->w) { + x = 0; + ++y; + } + } + /* Compute position and size of bounding box. */ + if (xmin <= xmax && ymin <= ymax) { + img->bboxx = xmin; img->bboxy = ymin; + img->bboxw = xmax - xmin; img->bboxh = ymax - ymin; + } + } + + // GDL I/O + + void + interp_image(ImageFamily *imf, Obj *size, Obj *parts) + { + int w, h, imtype, emx, emy, emw, emh, numsubs, subi; + char *name; + Image *img, *subimg; + Obj *head, *rest, *typ, *prop, *proptype, *datalist; + + w = c_number(car(size)); h = c_number(cadr(size)); + img = get_img(imf, w, h); + if (img == NULL) + run_error("no image?"); + if (img->w == 1 && img->h == 1) { + /* A color is more like a tile than an icon. */ + img->istile = TRUE; + img->palette = cons(cons(new_number(0), parts), lispnil); + return; + } + if (match_keyword(car(cddr(size)), K_TILE)) + img->istile = TRUE; + if (match_keyword(car(cddr(size)), K_TERRAIN)) + img->isterrain = TRUE; + if (match_keyword(car(cddr(size)), K_CONNECTION)) + img->isconnection = TRUE; + if (match_keyword(car(cddr(size)), K_BORDER)) + img->isborder = TRUE; + if (match_keyword(car(cddr(size)), K_TRANSITION)) + img->istransition = TRUE; + numsubs = 0; + for_all_list(parts, rest) { + head = car(rest); + typ = car(head); + imtype = K_OTHER_; + if (match_keyword(typ, K_MONO)) { + imtype = K_MONO_; + } else if (match_keyword(typ, K_MASK)) { + imtype = K_MASK_; + } else if (match_keyword(typ, K_COLOR)) { + imtype = K_COLR_; + } else if (match_keyword(typ, K_FILE)) { + imtype = K_FILE_; + } else if (match_keyword(typ, K_EMBED)) { + name = c_string(cadr(head)); + if (img->embedname != NULL + && strcmp(img->embedname, name) != 0) + run_warning("Changing embed name from \"%s\" to \"%s\" in %dx%d image of \"%s\"", + img->embedname, name, w, h, imf->name); + img->embedname = name; + } else if (match_keyword(typ, K_EMBED_AT)) { + emx = c_number(cadr(head)); emy = c_number(caddr(head)); + if ((img->embedx >= 0 && emx != img->embedx) + || (img->embedy >= 0 && emy != img->embedy)) + run_warning("Changing embed x,y from %d,%d to %d,%d in %dx%d image of \"%s\"", + img->embedx, img->embedy, emx, emy, w, h, imf->name); + img->embedx = emx; img->embedy = emy; + } else if (match_keyword(typ, K_EMBED_SIZE)) { + emw = c_number(cadr(head)); emh = c_number(caddr(head)); + if ((img->embedw >= 0 && emw != img->embedw) + || (img->embedh >= 0 && emh != img->embedh)) + run_warning("Changing embed w,h from %d,%d to %d,%d in %dx%d image of \"%s\"", + img->embedw, img->embedh, emw, emh, w, h, imf->name); + img->embedw = emw; img->embedh = emh; + } else if (match_keyword(typ, K_HEXGRID)) { + img->hexgridx = c_number(cadr(head)); + img->hexgridy = c_number(caddr(head)); + numsubs = img->hexgridx*img->hexgridy; + } else if (match_keyword(typ, K_NOTES)) { + img->notes = cadr(head); + syntax_error(head, "extra junk after image notes property"); + } else if (match_keyword(typ, K_X)) { + numsubs = c_number(cadr(head)); + if (cddr(head) != lispnil) { + img->subx = c_number(caddr(head)); + img->suby = c_number(car(cdddr(head))); + } + } else { + run_warning("unknown image property in \"%s\"", imf->name); + } + /* If there is no actual image data to process, skip to the next + clause in the form. */ + if (imtype == K_OTHER_) + continue; + datalist = cdr(head); + /* Interpret random image subproperties. */ + while (consp(car(datalist))) { + prop = car(datalist); + proptype = car(prop); + if (match_keyword(proptype, K_ACTUAL)) { + img->actualw = c_number(cadr(prop)); + img->actualh = c_number(caddr(prop)); + } else if (match_keyword(proptype, K_PIXEL_SIZE)) { + img->pixelsize = c_number(cadr(prop)); + } else if (match_keyword(proptype, K_PALETTE)) { + img->palette = cdr(prop); + } else { + char imferrbuf[200]; + + sprintlisp(imferrbuf, prop, 100); + run_warning("unknown image subproperty in \"%s\": %s", + imf->name, imferrbuf); + } + datalist = cdr(datalist); + } + switch (imtype) { + case K_MONO_: + if (img->monodata != lispnil && !equal(datalist, img->monodata)) + run_warning("Changing mono data in %dx%d image of \"%s\"", + w, h, imf->name); + img->monodata = datalist; + break; + case K_COLR_: + if (img->colrdata != lispnil && !equal(datalist, img->colrdata)) + run_warning("Changing color data in %dx%d image of \"%s\"", + w, h, imf->name); + img->colrdata = datalist; + break; + case K_MASK_: + if (img->maskdata != lispnil && !equal(datalist, img->maskdata)) + run_warning("Changing mask data in %dx%d image of \"%s\"", + w, h, imf->name); + img->maskdata = datalist; + break; + case K_FILE_: + if (img->filedata != lispnil && !equal(datalist, img->filedata)) + run_warning("Changing file data in %dx%d image of \"%s\"", + w, h, imf->name); + img->filedata = datalist; + break; + default: + break; + } + } + /* Allocate space for any subimages that might be needed. */ + /* First set some standard numbers of subimages. */ + if (img->isborder) { + numsubs = 16; + } else if (img->isconnection) { + numsubs = 64; + } else if (img->istransition) { + numsubs = 4 * 4; + /* Limit the number of terrain subimages if we lack memory. */ + } else if (poor_memory) { /* FIXME - what about hexgrid? */ + numsubs = min(numsubs, 3); + } + /* Deal with possible weird situations. */ + if (img->numsubimages > 0 && numsubs != img->numsubimages) { + run_warning("Going from %d to %d subimages in %dx%d image of \"%s\"", + img->numsubimages, numsubs, w, h, imf->name); + img->subimages = NULL; + } + img->numsubimages = numsubs; + if (img->subimages == NULL) { + img->subimages = (Image **) xmalloc(numsubs * sizeof(Image *)); + for (subi = 0; subi < numsubs; ++subi) { + subimg = get_subimg(imf, img->w, img->h); + img->subimages[subi] = subimg; + } + } + } NAMESPACE_GDL_END |