• xbattle 4.0 (portability) fixes

    From Ivan Shmakov@ivan@siamics.netREMOVE.invalid to comp.windows.x on Wed Feb 11 08:37:07 2026
    From Newsgroup: comp.windows.x

    First of all, a fair warning: the license for xbattle is confusing:

    README> COPYRIGHT

    README> Copied from the GNU Emacs 'copyleft' policy. Basically, you
    README> are free to copy, modify and distribute this program as long
    README> as you do not sell it or use it in a product that you sell.

    The "do not sell" restriction would make this software fail the
    FSF free software criteria, but at the same time, the license
    text itself mentions no such restrictions. It goes on to state:

    README> c) You may charge a distribution fee for the physical act of
    README> transferring a copy, and you may at your option offer warranty
    README> protection in exchange for a fee.

    Now, unlike many free software enthusiasts, I do not consider
    the /use/ of (possibly, in this case) non-free software to be
    an ethical issue per se, but endorsing it is clearly questionable
    in that department.

    So there.

    Now, there're two issues with xbattle 4.0 as shipped (e. g.,
    http://ftp.gwdg.de/pub/x11/x.org/R5contrib/xbattle-4.0.tar.Z ):

    a. main.c seems to misuse XSetIOErrorHandler and FD_SET in main,
    and also XLookupString and XDrawImageString in process_event;
    I have a straightforward patch from 2002 (below) fixing that;

    b. it checks if the display supports a 8 bits per pixel PseudoColor
    visual, and uses monochrome if that's not the case; this is where
    I had to get creative.

    What I've used for b. is: a. add new bw_p field to xwindow_type
    in extern.h; b. make it used consistently in the code in place
    of xwindow->depth tests; c. replaced the initial tests like:

    - if(xwindow->depth != 8)
    - {
    - if (XMatchVisualInfo(xwindow->display, xwindow->screen, 8, PseudoColor, &vinfo))
    - {
    - visual = vinfo.visual;
    - xwindow->depth = 8;
    - }

    + if (xwindow->depth == 8) {
    + xwindow->bw_p = 0;
    + } else if (XMatchVisualInfo (xwindow->display, xwindow->screen,
    + 8, PseudoColor, &vinfo)
    + || XMatchVisualInfo (xwindow->display, xwindow->screen,
    + 15, TrueColor, &vinfo)
    + || /* ... and so on... */

    So far I'm testing for PseudoColor at depth 8, and TrueColor
    visuals at depths 15, 16, 24, 32.

    And the question is: what's an easy way to check for a TrueColor
    (PseudoColor) visual having /at least/ a given depth?

    TIA. The diffs follow.

    --- xbattle-4.0/main.c 1992-09-27 16:52:19 +0000
    +++ xbattle-4.0/main.c 2002-03-26 09:06:18 +0000
    @@ -155,7 +155,7 @@ main(argc,argv)

    /************* main event loop *************/
    #if UNIX
    - XSetIOErrorHandler(1);
    + /* XSetIOErrorHandler(1); */
    gettimeofday (&tp_old, &tzp);
    oldtime = (tp_old.tv_sec%10000)*1000000 + tp_old.tv_usec;
    targettime = oldtime + (delay/10000)*1000000 + (delay%10000)*100;
    @@ -207,7 +207,8 @@ main(argc,argv)
    {
    if (winopen[i])
    {
    - if (FD_SET(fd = ConnectionNumber(xwindow[i]->display), &rfds))
    + fd = ConnectionNumber(xwindow[i]->display);
    + if (FD_ISSET(fd, &rfds))
    {
    while (winopen[i] &&
    XEventsQueued(xwindow[i]->display, QueuedAfterReading) > 0)
    @@ -543,7 +544,7 @@ process_event(event,board,colorarray,pla

    /**** process key press events ****/
    case KeyPress:
    - textcount = XLookupString(&event, text, 10, &key, NULL);
    + textcount = XLookupString(&(event.xkey), text, 10, &key, NULL);
    if (textcount != 0)
    {
    if ((enable_hex && (event.xbutton.y < boardsizey*2*hex_vert + hex_vert)) ||
    @@ -1208,7 +1209,7 @@ replaygame(squaresize,board)
    for (l=0; l<nsides; l++)
    XDrawImageString(xwindow[k]->display,xwindow[k]->window,
    xwindow[k]->hue[light],
    - TEXTX,textyh[l],
    + TEXTX,*(textyh[l]),
    messagestr,strlen(messagestr));
    #else
    XDrawImageString(xwindow[k]->display,xwindow[k]->window,
    --- xbattle-4.0-build/draw.c.~1~ 1992-09-27 16:52:24 +0000
    +++ xbattle-4.0-build/draw.c 2026-01-24 19:28:30 +0000
    @@ -342,8 +342,8 @@ drawsquare(xwindow,square,windowcolor,sq
    else
    {
    onhue = xwindow->hue[square->color];
    - if ((xwindow->depth==1 && color2bw[sidemap[square->color]]<=GRAY3) ||
    - (xwindow->depth==8 && sidemap[square->color]==BLACK))
    + if (xwindow->bw_p ? color2bw[sidemap[square->color]]<=GRAY3
    + : sidemap[square->color]==BLACK)
    offhue = xwindow->hue[light];
    else
    offhue = xwindow->hue[dark];
    --- xbattle-4.0-build/extern.h.~1~ 1992-09-27 16:52:24 +0000
    +++ xbattle-5.0-build/extern.h 2026-01-24 19:17:38 +0000
    @@ -103,7 +103,7 @@ typedef struct{
    int xsize,ysize;
    XSizeHints hint;
    XWMHints xwmh;
    - int depth,screen;
    + int bw_p,depth,screen;
    GC hue[MAXSIDES+3], flip, gc_clear, gc_or;
    Pixmap terrain[NHILLTONES];
    XFontStruct *font_struct;
    --- xbattle-4.0-build/utils.c.~1~ 1992-09-27 16:52:33 +0000
    +++ xbattle-4.0-build/utils.c 2026-01-25 11:13:16 +0000
    @@ -1,4 +1,6 @@
    #include <stdio.h>
    +#include <string.h>
    +#include <time.h>

    /**** x include files ****/
    #include <X11/Xlib.h>
    @@ -74,20 +76,27 @@ open_xwindow(xwindow,displayname,xpos,yp

    visual = DefaultVisual(xwindow->display,xwindow->screen);

    - if(xwindow->depth != 8)
    - {
    - if (XMatchVisualInfo(xwindow->display, xwindow->screen, 8, PseudoColor, &vinfo))
    - {
    - visual = vinfo.visual;
    - xwindow->depth = 8;
    - }
    + /** FIXME: add a command line option for black and white rendering */
    + if (xwindow->depth == 8) {
    + xwindow->bw_p = 0;
    + } else if (XMatchVisualInfo (xwindow->display, xwindow->screen,
    + 8, PseudoColor, &vinfo)
    + /** FIXME: is this still a sensible approach? */
    + || XMatchVisualInfo (xwindow->display, xwindow->screen,
    + 15, TrueColor, &vinfo)
    + || XMatchVisualInfo (xwindow->display, xwindow->screen,
    + 16, TrueColor, &vinfo)
    + || XMatchVisualInfo (xwindow->display, xwindow->screen,
    + 24, TrueColor, &vinfo)
    + || XMatchVisualInfo (xwindow->display, xwindow->screen,
    + 32, TrueColor, &vinfo)) {
    + visual = vinfo.visual;
    + xwindow->bw_p = 0;
    + } else {
    + xwindow->bw_p = 1;
    }

    - if (xwindow->depth != 8)
    - xwindow->depth = 1;
    -
    - if(xwindow->depth == 8)
    - {
    + if (! xwindow->bw_p) {
    /**** create color map using visual ****/
    #if NEWCOLORMAP
    xwindow->cmap = XCreateColormap(xwindow->display,
    @@ -123,11 +132,10 @@ open_xwindow(xwindow,displayname,xpos,yp
    }

    /**** get standard properties for window manager ****/
    - if (xwindow->depth == 8)
    + if (! xwindow->bw_p)
    XSetStandardProperties(xwindow->display, xwindow->window, htitle, htitle,
    None, NULL, None, &xwindow->hint);
    - else if (xwindow->depth == 1)
    - {
    + else {
    XSetStandardProperties(xwindow->display, xwindow->window, gtitle, gtitle,
    None, NULL, None, &xwindow->hint);
    }
    @@ -142,8 +150,7 @@ open_xwindow(xwindow,displayname,xpos,yp
    XSelectInput(xwindow->display, xwindow->window, eventmask);

    /**** load color map ****/
    - if(xwindow->depth == 8)
    - {
    + if(! xwindow->bw_p) {
    for (i=0 ; i<MAXCOLORS ; i++)
    {
    xwindow->xcolor[i].flags = 0;
    @@ -307,8 +314,7 @@ open_xwindow(xwindow,displayname,xpos,yp
    XSetFunction(xwindow->display, xwindow->flip, GXinvert);

    /**** set drawing colors ****/
    - if (xwindow->depth == 1)
    - {
    + if (xwindow->bw_p) {
    for (j=0; j<nsides; j++) {

    if (color2bw[sidemap[j]] == WHITE)
    @@ -350,7 +356,7 @@ open_xwindow(xwindow,displayname,xpos,yp
    }

    /**** set colors (link GC to color) ****/
    - if (xwindow->depth == 8)
    + if (! xwindow->bw_p)
    {
    #if NEWCOLORMAP
    for (j=0; j<nsides; j++)
    @@ -387,8 +393,7 @@ open_xwindow(xwindow,displayname,xpos,yp
    }
    }

    - if (xwindow->depth == 1)
    - {
    + if (xwindow->bw_p) {
    /**** set grey stipple color ****/

    init_stipple (xwindow->display, xwindow->window, stipple);
    @@ -426,7 +431,7 @@ open_xwindow(xwindow,displayname,xpos,yp
    squaresize, squaresize, xwindow->depth);
    }

    - if (xwindow->depth == 8)
    + if (! xwindow->bw_p)
    {
    for (i=0; i<limit; i++)
    {
    @@ -438,7 +443,7 @@ open_xwindow(xwindow,displayname,xpos,yp
    terrainhue[i], 0, 0, squaresize, squaresize);
    }
    }
    - else if (xwindow->depth == 1)
    + else if (xwindow->bw_p)
    {
    if (enable_hex)
    init_terrain_pixmaps (xwindow, limit, 2*hex_side);
    @@ -544,7 +549,7 @@ open_xwindow(xwindow,displayname,xpos,yp
    XSetFont(xwindow->display, xwindow->flip, xwindow->font_struct->fid);
    }

    - if (xwindow->depth == 1)
    + if (xwindow->bw_p)
    {
    for (i=0; i<nsides; i++)
    {
    @@ -567,8 +572,8 @@ open_xwindow(xwindow,displayname,xpos,yp
    xwindow->drawletter[none] = FALSE;

    /**** map window to make it visible ****/
    - if (xwindow->depth == 8)
    - XMapWindow(xwindow->display, xwindow->window);
    + /* FIXME: ? if (! xwindow->bw_p) */
    + XMapWindow(xwindow->display, xwindow->window);
    }


    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.windows.x on Wed Feb 11 22:58:04 2026
    From Newsgroup: comp.windows.x

    On Wed, 11 Feb 2026 08:37:07 +0000, Ivan Shmakov wrote:

    First of all, a fair warning: the license for xbattle is confusing:

    README> COPYRIGHT

    README> Copied from the GNU Emacs 'copyleft' policy. Basically, you
    README> are free to copy, modify and distribute this program as
    README> long as you do not sell it or use it in a product that you
    README> sell.

    The "do not sell" restriction would make this software fail the
    FSF free software criteria, but at the same time, the license text
    itself mentions no such restrictions.

    Is the distinction between rCLcopyleftrCY and rCLnon-commercialrCY really that subtle, that some people are capable of being confused by it? The two
    have nothing to do with each other, no matter what the xbattle
    developer(s) may think.

    In particular, rCLcopyleftrCY is a well-defined concept, while rCLnon-commercialrCY is not.
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Eli the Bearded@*@eli.users.panix.com to comp.windows.x on Thu Feb 12 06:53:49 2026
    From Newsgroup: comp.windows.x

    In comp.windows.x, Lawrence DOliveiro <ldo@nz.invalid> wrote:
    On Wed, 11 Feb 2026 08:37:07 +0000, Ivan Shmakov wrote:
    ^^^^

    Is the distinction between "copyleft" and "non-commercial" really that subtle, that some people are capable of being confused by it? The two
    have nothing to do with each other, no matter what the xbattle
    developer(s) may think.

    In particular, "copyleft" is a well-defined concept, while
    "non-commercial" is not.

    That's very easy for you to say 34 years after the code was packaged.
    The license included probably dates to the 1991 release (I found a date
    of "10/1/91" in one file, the README just says "1991"), but the tar file referenced has all September 1992 files. The nuances of different open
    source licenses were not well publicized at the time. The FSF probably
    didn't have a website in September 1992.

    After applying Ivan's patches, I also needed to add some includes to
    main.c, and then changed the C standard in the Makefile. Note that
    the Makefile is generated by xmkmf, and not included in the source.
    I don't know enough imake to know if/how I should have modified that.

    --- a/main.c
    +++ b/main.c
    @@ -1,4 +1,6 @@
    #include <stdio.h>
    +#include <stdlib.h>
    +#include <string.h>

    /**** x include files ****/
    #include <X11/Xlib.h>

    --- a/Makefile
    +++ b/Makefile
    @@ -323,7 +323,7 @@ MODLDCOMBINEFLAGS = -r
    PROJECTROOT = /usr

    CDEBUGFLAGS = -g -O2 -fno-strict-aliasing
    - CCOPTIONS =
    + CCOPTIONS = -std=c89

    ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(INSTALLED_INCLUDES) $(STD_INCLUDES)
    ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(THREADS_DEFINES) $(MODULE_DEFINES) $(DEFINES) $(EXTRA_DEFINES)


    That got me an executible that runs, but all I can get it to do is spit
    out usage.

    $ /xbattle -hex -board 100 -horizon 20 -map -localmap
    USAGE: xbattle
    -<c1> <display> display name side uses color c1 with
    default color to b/w mapping
    -<c1><c2> <display> display name side uses color c1 with
    b/w terminals using b/w shade c2
    -hex Use hexagonal display
    [... many lines ...]

    So I'm not sure how to actually run it. Possibly a read of the code
    would be helpful.

    Elijah
    ------
    might look at the start-up code tomorrow
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.windows.x on Thu Feb 12 19:11:47 2026
    From Newsgroup: comp.windows.x

    On Thu, 12 Feb 2026 06:53:49 -0000 (UTC), Eli the Bearded wrote:

    In comp.windows.x, Lawrence DOliveiro <ldo@nz.invalid> wrote:

    In particular, "copyleft" is a well-defined concept, while
    "non-commercial" is not.

    The nuances of different open source licenses were not well
    publicized at the time [34 years ago].

    rCLPublicizedrCY or not, it behooves a developer to at least read and understand the licence thay are considering using, does it not?
    After all, they were going to include a copy with their code.
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Eli the Bearded@*@eli.users.panix.com to comp.windows.x on Thu Feb 12 23:57:36 2026
    From Newsgroup: comp.windows.x

    In comp.windows.x, Lawrence DOliveiro <ldo@nz.invalid> wrote:
    "Publicized" or not, it behooves a developer to at least read and
    understand the licence thay are considering using, does it not?
    After all, they were going to include a copy with their code.

    The "license" is not called that. It's called "COPYING POLICIES" and
    it seems to be a modified, and perhaps shortened, crib from a license
    from some version of GNU Emacs.

    Oh, and I figured out how to get it run now. I had overlooked there's a
    man page included. This is old-school X11 and multiplayer relies on
    this one program being able to open windows on a remote system. So to
    just see the game, the most basic command line would be:

    xbattle -red me

    (Which is a rather plain looking grid.)

    Or any x11 color:

    xbattle -$X11_COLOR_NAME me

    Multiple player takes the hostname and $DISPLAY:

    xbattle -red me -blue lawrence:0.0

    Then the other options are optional, but you get more of a game board.

    This died with a "Memory fault":

    xbattle -red me -hex -board 100

    But this gave me a complicated board:

    xbattle -red me -hex -board 20 -horizon 4 -map -localmap \
    -bases 10 -rbases 2 -armies 5 -militia 10 -hills 2 \
    -forest 3 -sea 1 -farms 2 -erode 2 -decay 2 -towns 3 \
    -guns 4 -para 4 -fight 1 -speed 1 -move 2 -digin 2

    There's a noticable delay between starting the program and the board
    getting drawn in the window. I could click around and things changed,
    but not much, it wasn't clear what was happening. A more careful read
    of the man page would probably help.

    Elijah
    ------
    wondering what other memory faults lurk in the code
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Ivan Shmakov@ivan@siamics.netREMOVE.invalid to comp.windows.x on Fri Feb 13 21:15:45 2026
    From Newsgroup: comp.windows.x

    On 2026-02-12, Eli the Bearded wrote:
    In comp.windows.x, Lawrence DOliveiro <ldo@nz.invalid> wrote:
    On Thu, 12 Feb 2026 06:53:49 -0000 (UTC), Eli the Bearded wrote:

    After applying Ivan's patches, I also needed to add some includes
    to main.c, and then changed the C standard in the Makefile.

    --- a/main.c
    +++ b/main.c
    @@ -1,4 +1,6 @@
    #include <stdio.h>
    +#include <stdlib.h>
    +#include <string.h>

    ACK, thanks.

    - CCOPTIONS =
    + CCOPTIONS = -std=c89

    I will keep that in mind, but I'm going to guess that's needed
    only when C23 is being the default. I've used GCC 10.5.0 myself,
    and at a glance, it requires no -std= options for this code.

    "Publicized" or not, it behooves a developer to at least read and
    understand the licence thay are considering using, does it not?
    After all, they were going to include a copy with their code.

    The "license" is not called that. It's called "COPYING POLICIES"
    and it seems to be a modified, and perhaps shortened, crib from a
    license from some version of GNU Emacs.

    I'm going to concur. One or both of the authors of this code
    apparently misunderstood the point of copyleft - back when it
    wasn't something widely known. So sue them.

    Oh, and I figured out how to get it run now. I had overlooked
    there's a man page included.

    There're also tutorial1 and tutorial2 shell scripts that are
    supposed to introduce new players to the game by starting it
    up with different options, beginning with the most simple
    arrangements.

    This is old-school X11 and multiplayer relies on this one program
    being able to open windows on a remote system.

    I'd call it a multi-display multiplayer game. The display(s)
    in question need not be remote: it's possible to explore game
    mechanics with, say, -red me -blue me, and it's also possible
    to play from local Xvnc instances (-red me -blue :29 -cyan :43)
    - accessed through remote VNC clients.

    When using X, my suggestion these days would be to use a nested
    X server, such as Xephyr or Xnest, rather than granting access
    to one's "primary" one with xauth or xhost.

    There're at least two games like that currently in pkgsrc -
    craft and spellcast - and I hope to add xbattle and xtank to
    the list as well. (I've got xtank to build and run, but the AI
    is not functional, and I'm yet to try to fix that.)

    This died with a "Memory fault":

    xbattle -red me -hex -board 100

    I guess I can link it against Electric Fence and take a closer
    look for possible out-of-bounds array accesses (assuming that's
    what's happening here.)

    But this gave me a complicated board:

    xbattle -red me -hex -board 20 -horizon 4 -map -localmap \
    -bases 10 -rbases 2 -armies 5 -militia 10 -hills 2 \
    -forest 3 -sea 1 -farms 2 -erode 2 -decay 2 -towns 3 \
    -guns 4 -para 4 -fight 1 -speed 1 -move 2 -digin 2

    There's a noticable delay between starting the program and the board
    getting drawn in the window.

    Not something I've personally noticed, but I suppose it might
    depend on the specific options used.

    I could click around and things changed, but not much, it wasn't
    clear what was happening. A more careful read of the man page would probably help.

    I've actually thought of including a summary of the game in the
    initial post, then decided against it - for the sake of keeping
    to the point.

    Basically, each grid cell (square or hexagon) may contain
    armies of a player. That player can click near a side of that
    cell to order armies to start crossing that side into adjacent
    cell. More than one order can be active; left-click toggles
    orders, middle-click overrides all orders with a single new one.

    Encountering enemy armies results in fights. With -rbases,
    -towns and -farms, it's possible to replentish armies, so it
    becomes necessary to set orders in cells in a way to form
    supply lines from towns to the line(s) of conflict. Overall,
    it results in a gameplay somewhat reminiscent of Liquidwar.

    FWIW, the options I've used to start games back in the day are:

    -hex -board 12 -area -map -localmap -horizon -bound -march 4
    -repeat -attack -reserve -scuttle -farms 7 -decay 2
    -sea 8 -towns 3 -hills 4 -forest 4 -fill 4 -dig 4 -build 8
    -guns 5 -para 5 -rbases 1 -militia 3
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.windows.x on Fri Feb 13 21:51:30 2026
    From Newsgroup: comp.windows.x

    On Thu, 12 Feb 2026 23:57:36 -0000 (UTC), Eli the Bearded wrote:

    In comp.windows.x, Lawrence DOliveiro <ldo@nz.invalid> wrote:

    "Publicized" or not, it behooves a developer to at least read and
    understand the licence thay are considering using, does it not?
    After all, they were going to include a copy with their code.

    The "license" is not called that. It's called "COPYING POLICIES" and
    it seems to be a modified, and perhaps shortened, crib from a
    license from some version of GNU Emacs.

    Nasty.
    --- Synchronet 3.21b-Linux NewsLink 1.2