/* -*-c-*-
*
- * $Id: elite.c,v 1.1 2003/02/24 01:13:12 mdw Exp $
- *
* Elite planet data
*
* (c) 2003 Mark Wooding
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This program 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 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: elite.c,v $
- * Revision 1.1 2003/02/24 01:13:12 mdw
- * Initial import.
- *
- */
-
/*----- Header files ------------------------------------------------------*/
#include <ctype.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tcl.h>
+
/*----- Data structures ---------------------------------------------------*/
typedef struct world {
o->bytes = p;
o->length = 12;
for (i = 0; i < 6; i++, p += 2)
- sprintf(p, "%02x", w->x[i]);
+ sprintf(p, "%02x", w->x[i]);
}
static void world_dir(Tcl_Obj *o, Tcl_Obj *oo)
p++;
j = mangle(w);
goatsoup(d, pn, w, desc[i][(j >= 0x33) + (j >= 0x66) +
- (j >= 0x99) + (j >= 0xcc)]);
+ (j >= 0x99) + (j >= 0xcc)]);
break;
case '%':
p++;
world ww;
/* --- Check arguments --- */
-
+
if (objc != 3)
return (err(ti, "usage: elite-worldinfo ARR SEED"));
if ((w = world_get(ti, objv[2])) == 0)
/* --- Get the basic information --- */
getworldinfo(&wi, w);
+ Tcl_UnsetVar(ti, arr, 0);
if (!Tcl_SetVar2Ex(ti, arr, "x", Tcl_NewIntObj(wi.x * 4),
TCL_LEAVE_ERR_MSG) ||
!Tcl_SetVar2Ex(ti, arr, "y", Tcl_NewIntObj(wi.y * 2),
TCL_LEAVE_ERR_MSG) ||
- !Tcl_SetVar2Ex(ti, arr, "government", Tcl_NewIntObj(wi.gov),
+ !Tcl_SetVar2Ex(ti, arr, "government", Tcl_NewIntObj(wi.gov),
TCL_LEAVE_ERR_MSG) ||
!Tcl_SetVar2Ex(ti, arr, "economy", Tcl_NewIntObj(wi.eco),
TCL_LEAVE_ERR_MSG) ||
- !Tcl_SetVar2Ex(ti, arr, "techlevel", Tcl_NewIntObj(wi.tech),
+ !Tcl_SetVar2Ex(ti, arr, "techlevel", Tcl_NewIntObj(wi.tech),
TCL_LEAVE_ERR_MSG) ||
- !Tcl_SetVar2Ex(ti, arr, "population", Tcl_NewIntObj(wi.pop),
+ !Tcl_SetVar2Ex(ti, arr, "population", Tcl_NewIntObj(wi.pop),
TCL_LEAVE_ERR_MSG) ||
- !Tcl_SetVar2Ex(ti, arr, "productivity", Tcl_NewIntObj(wi.prod),
+ !Tcl_SetVar2Ex(ti, arr, "productivity", Tcl_NewIntObj(wi.prod),
TCL_LEAVE_ERR_MSG) ||
!Tcl_SetVar2Ex(ti, arr, "radius", Tcl_NewIntObj(wi.rad),
TCL_LEAVE_ERR_MSG) ||
return (TCL_ERROR);
getworldinfo(&wi, w);
+ Tcl_UnsetVar(ti, arr, 0);
for (i = items; i->name; i++) {
unsigned pr, qt;
Tcl_Obj *oo[2];
return (-1);
*p++ = ii;
}
- return (0);
+ return (0);
}
static struct cmddata cmdtab[] = {
/* --- Deconstruct the data --- */
+ Tcl_UnsetVar(ti, arr, 0);
for (c = cmdtab; c->name; c++) {
if (c->get && c->get(ti, arr, p + c->off, c))
return (TCL_ERROR);
return (0);
}
+/*----- Optimizations -----------------------------------------------------*/
+
+/* --- @elite-galaxylist SEED@ --- *
+ *
+ * Returns a SEED/X/Y list for the worlds in galaxy SEED.
+ */
+
+static int cmd_galaxylist(ClientData cd, Tcl_Interp *ti,
+ int objc, Tcl_Obj *const *objv)
+{
+ world *w, ww;
+ worldinfo wi;
+ int i;
+ Tcl_Obj *o;
+
+ if (objc != 2)
+ return (err(ti, "usage: elite-galaxylist SEED"));
+ if ((w = world_get(ti, objv[1])) == 0)
+ return (TCL_ERROR);
+ ww = *w;
+ o = Tcl_NewListObj(0, 0);
+ for (i = 0; i < 256; i++) {
+ getworldinfo(&wi, &ww);
+ Tcl_ListObjAppendElement(ti, o, world_new(&ww));
+ Tcl_ListObjAppendElement(ti, o, Tcl_NewIntObj(wi.x * 4));
+ Tcl_ListObjAppendElement(ti, o, Tcl_NewIntObj(wi.y * 2));
+ waggle(&ww, &ww); waggle(&ww, &ww); waggle(&ww, &ww); waggle(&ww, &ww);
+ }
+ Tcl_SetObjResult(ti, o);
+ return (TCL_OK);
+}
+
+/* --- @elite-distance X Y XX YY@ --- *
+ *
+ * Returns the distance between two points.
+ */
+
+static int cmd_distance(ClientData cd, Tcl_Interp *ti,
+ int objc, Tcl_Obj *const *objv)
+{
+ long x, y, xx, yy;
+ long d;
+
+ if (objc != 5)
+ return (err(ti, "usage: elite-distance X Y XX YY"));
+ if (Tcl_GetLongFromObj(ti, objv[1], &x) != TCL_OK ||
+ Tcl_GetLongFromObj(ti, objv[2], &y) != TCL_OK ||
+ Tcl_GetLongFromObj(ti, objv[3], &xx) != TCL_OK ||
+ Tcl_GetLongFromObj(ti, objv[4], &yy) != TCL_OK)
+ return (TCL_ERROR);
+ xx = xx >= x ? xx - x : x - xx; xx >>= 2; xx *= xx;
+ yy = yy >= y ? yy - y : y - yy; yy >>= 2; yy *= yy;
+ d = sqrt(xx + yy); d <<= 2;
+ Tcl_SetObjResult(ti, Tcl_NewLongObj(d));
+ return (TCL_OK);
+}
+
+/* --- @elite-adjacency ADJ LIST [DIST]@ --- *
+ *
+ * Construct an adjacency table from a world list.
+ */
+
+static int cmd_adjacency(ClientData cd, Tcl_Interp *ti,
+ int objc, Tcl_Obj *const *objv)
+{
+ int oc;
+ Tcl_Obj **ov;
+ size_t i, j;
+ long x, y, xx, yy, d;
+ Tcl_Obj *a;
+ char *s, *ss;
+ Tcl_HashTable done;
+ long dd = 70;
+ int rc = TCL_ERROR;
+ int dummy;
+ Tcl_Obj *o;
+
+ if (objc < 3 || objc > 4)
+ return (err(ti, "usage: elite-adjacency ADJ LIST [DIST]"));
+ a = objv[1];
+ if (Tcl_ListObjGetElements(ti, objv[2], &oc, &ov) != TCL_OK)
+ return (TCL_ERROR);
+ if (oc % 3 != 0)
+ return (err(ti, "world array not a multiple of three in size"));
+ if (objc >= 4 && Tcl_GetLongFromObj(ti, objv[3], &dd) != TCL_OK)
+ return (TCL_ERROR);
+
+ Tcl_InitHashTable(&done, TCL_ONE_WORD_KEYS);
+ Tcl_UnsetVar(ti, Tcl_GetString(a), 0);
+ o = Tcl_NewObj();
+ Tcl_IncrRefCount(o);
+ for (i = 0; i < oc; i += 3) {
+ s = Tcl_GetString(ov[i]);
+ if (Tcl_ObjSetVar2(ti, a, ov[i], o, TCL_LEAVE_ERR_MSG) == 0)
+ goto done;
+ }
+ for (i = 0; i < oc; i += 3) {
+ s = Tcl_GetString(ov[i]);
+ Tcl_CreateHashEntry(&done, s, &dummy);
+ if (Tcl_GetLongFromObj(ti, ov[i + 1], &x) != TCL_OK ||
+ Tcl_GetLongFromObj(ti, ov[i + 2], &y) != TCL_OK)
+ goto done;
+ for (j = 0; j < oc; j += 3) {
+ ss = Tcl_GetString(ov[j]);
+ if (Tcl_FindHashEntry(&done, ss))
+ continue;
+ if (Tcl_GetLongFromObj(ti, ov[j + 1], &xx) != TCL_OK ||
+ Tcl_GetLongFromObj(ti, ov[j + 2], &yy) != TCL_OK)
+ goto done;
+ xx = xx >= x ? xx - x : x - xx; xx >>= 2; xx *= xx;
+ yy = yy >= y ? yy - y : y - yy; yy >>= 2; yy *= yy;
+ d = sqrt(xx + yy); d <<= 2;
+ if (d <= dd) {
+ if (Tcl_ObjSetVar2(ti, a, ov[i], ov[j],
+ (TCL_APPEND_VALUE |
+ TCL_LIST_ELEMENT |
+ TCL_LEAVE_ERR_MSG)) == 0 ||
+ Tcl_ObjSetVar2(ti, a, ov[i], ov[j + 1],
+ (TCL_APPEND_VALUE |
+ TCL_LIST_ELEMENT |
+ TCL_LEAVE_ERR_MSG)) == 0 ||
+ Tcl_ObjSetVar2(ti, a, ov[i], ov[j + 2],
+ (TCL_APPEND_VALUE |
+ TCL_LIST_ELEMENT |
+ TCL_LEAVE_ERR_MSG)) == 0 ||
+ Tcl_ObjSetVar2(ti, a, ov[j], ov[i],
+ (TCL_APPEND_VALUE |
+ TCL_LIST_ELEMENT |
+ TCL_LEAVE_ERR_MSG)) == 0 ||
+ Tcl_ObjSetVar2(ti, a, ov[j], ov[i + 1],
+ (TCL_APPEND_VALUE |
+ TCL_LIST_ELEMENT |
+ TCL_LEAVE_ERR_MSG)) == 0 ||
+ Tcl_ObjSetVar2(ti, a, ov[j], ov[i + 2],
+ (TCL_APPEND_VALUE |
+ TCL_LIST_ELEMENT |
+ TCL_LEAVE_ERR_MSG)) == 0)
+ goto done;
+ }
+ }
+ }
+ rc = TCL_OK;
+
+done:
+ Tcl_DeleteHashTable(&done);
+ return (rc);
+}
+
/*----- Initialization ----------------------------------------------------*/
int Elite_SafeInit(Tcl_Interp *ti)
} cmds[] = {
{ "elite-nextworld", cmd_nextworld },
{ "elite-nextgalaxy", cmd_nextgalaxy },
- { "elite-worldinfo", cmd_worldinfo },
+ { "elite-worldinfo", cmd_worldinfo },
{ "elite-market", cmd_market },
{ "elite-unpackcmdr", cmd_unpackcmdr },
{ "elite-packcmdr", cmd_packcmdr },
+ { "elite-distance", cmd_distance },
+ { "elite-galaxylist", cmd_galaxylist },
+ { "elite-adjacency", cmd_adjacency },
{ 0, 0 }
};
for (c = cmds; c->name; c++)
Tcl_CreateObjCommand(ti, c->name, c->proc, 0, 0);
Tcl_RegisterObjType(&world_type);
- if (Tcl_PkgProvide(ti, "elite-bits", "1.0.0"))
+ if (Tcl_PkgProvide(ti, "elite-bits", "1.0.1"))
return (TCL_ERROR);
return (TCL_OK);
}