Skip to content
Little GolemMake your next move.

JHEX

Public forum discussion.

Hex, Havannah

#1 · Ryan

31 Aug 2006

Could somebody please post a link where I can download JHEX? I used to have it, and I miss it now, haha.

#3 · Dvd Avins

31 Aug 2006

Not like you needed it to beat me, anyway.

#4 · Ryan

31 Aug 2006

I guess I assumed it wasn't very popular, and that it would be easier to ask here.

That's what assuming gets me. Thank you, though.

#6 · Art Duval

16 Sep 2006

I have found jhex, but I have a different problem. I would like to import games from LG (or Kurnik), and I have not figured out how to "import game records". The documentation on how to do this is not clear enough for me. Can anyone help? Even just an example of the proper format to type in to "paste game records into" the "Game Record Import" window would be so helpful. Thanks!

#7 · Marius Halsor

17 Sep 2006

I've made an application (in EXCEL, as that was what I had handy at the time :-) ) which translates from LG to JHex. I'll try to dig it up and see if I can still make it work. Send me your email adress if you want it.

#8 · Art Duval

18 Oct 2006

Although I had some problems with the implementation of Marius' EXCEL program, I did learn from that enough information to come up with a different solution of importing games to JHEX, which I would like to share, in case it's helpful to someone else. I'm very grateful to Marius for sending me his program, and explaining to me how it works. (And it may well work for other people; I have not used Excel much, so it was hard for me to do any sort of serious debugging.)

First off, what I learned was what JHEX wants (at least one version): something like "A3 I9 G7"; in other words, each move is identified just by its location (not who played it, not what number move it is), with capital letters for the letters, and spaces (no other punctuation) between moves. Then you import it in "simple" mode, "single game", and you explicitly state the board size, instead of letting JHEX try to guess it automatically.

So, I can first copy and paste the game record that shows up in the regular display of a game in LG (under the players names and nationalities) into an appropriate word processor. *If* that word processor knows about "regexp"s (regular expressions), it is easy to delete all the move numbers by searching for the regular expression

[0-9]+/.

and replacing it by, well, nothing (blank space would work, too). The "[0-9]" means any digits, the "+" means an arbitrary-length string consisting of said digits, and the "/." means literally the period (".") that the LG display puts after every move number. So we've now removed all the move numbers, and their corresponding periods. All that's left to do is put the letters of the move numbers into upper case.

Both these things (replacing [0-9]+/. by an empty string, and putting all letters into upper case) are easy to do in AlphaX, and, probably also emacs. It takes me about a minute with AlphaX.

I still don't know how to (easily) deal with swaps. Since I really want the JHEX board to look like the LG board, I have to rotate and flip the board, and manually reverse the colors (this is even if I simply enter all the moves on the JHEX board). In terms of importing, you would have to, on your own, figure out the new position of the swapped piece, in addition to rotating, flipping, and swapping colors. I'm curious to know if anyone else has a better solution for dealing with swaps.

#9 · Art Duval

18 Oct 2006

Sorry, that's

[0-9]+\.

(backslash instead of slash). I should have checked *before* sending the message.

#10 · Art Duval

14 Jan 2008

Bumping this to the top, since I mentioned it in another thread, about Six.

#11 · MarleysGhost

14 Jan 2008

http://canyon23.net/jgame/README_hex.html is the Jhex program that Hex players here recommend. It can save and read back a file containing multiple variations. It is not open source. (Also, since Kevin's Macintosh directions are for Mac OS 9 and previous, those using Mac OS X should follow the Unix directions.)

The Jhex at http://jhex.sourceforge.net is, obviously, open source, but AFAIK it does not read or write files.

#12 · Ruben Berenguel

14 Jan 2008

To all emacsers here (and also people who have it just installed, of course :)

<br/>(<span style="color: #a020f0;">defun</span> <span style="color: #0000ff;">LG-to-simple</span> ()<br/>  (interactive)<br/>  (beginning-of-buffer)<br/>  (<span style="color: #a020f0;">while</span> (re-search-forward <span style="color: #bc8f8f;">"[0-9]+\\."</span>  nil t)<br/>    (replace-match <span style="color: #bc8f8f;">""</span> nil nil))<br/>  (upcase-region (point-min) (point-max))<br/>)

Add this to your .emacs (and restart emacs), or just paste it in your *scratch* buffer, go to the last parenthesis and press C-j. Then you can just paste the game moves as they appear in game screen and just press M-x (ALT-x) and write LG-to-simple (or just LG and press tab, autocompletion should do fine). Then you can go on, like Art Duval explained. This just follows his guidelines, thanks for telling :) !

Disclaimer: I hope it works always, but have just written it. If you find any problem or have some question, feel free to ask (send me a message if you want).

#13 · Art Duval

15 Jan 2008

Marley: At this point, I don't recall which jhex I downloaded, though I think it was probably from canyon23. I also don't recall if I was clever enough to know to follow UNIX directions because I have Mac OS X. I have a sinking suspicion I went for the Mac instructions.

Ruben: Thanks for the automation tip! (But, see below.) Any idea how to use emacs to automate the swap?

Everyone: So I went back and looked at the documentation (what's the right phrase? RTFM?), and saw that, in fact, it's *not* necessary to strip away the move numbers, all that's necessary is to "upcase" the letters. For instance "1. A3 2. I9" is acceptable (I just tested it now).

I feel pretty stupid not noticing this last year. On the other hand, I expanded my knowledge of "regexp" [regular expressions] solving this problem the long way! :-)

#14 · Ruben Berenguel

15 Jan 2008

Yes, I RTFM after writing the little app. and realized it needn't erase the numbers, but this way also works, so... But upcasing in emacs is so easy that... well, you just paste, select and ctrl x ctrl u (first time a prompt will ask you whether you want upcase region or disable the command, as it is easy to misuse it as a beginner. For the swap thing... it would be possible, but not easy. I'll think about it, I also prefer it the LG way.

#15 · David J Bush

15 Jan 2008

Perhaps I should post in this thread as well:

1. Jhex and JTwixt were written by the same author, Kevin Walker. This suggests the binary format of .hgt and .tgt files are similar.

2. Alan Hensel has a Ruby skript on his info page which downloads Twixt games from LG and turns them into binary Jtwixt files. He even takes care of the swap problem so the default Jtwixt orientation is always the same as the LG display.

Maybe someone familiar with Ruby would like to take a look at this skript, and see if it could be modified to do the same thing for Jhex. In the long run this seems like a much better solution.

#16 · Carroll

17 Jan 2008

Here is the ruby script for hex (I called it gethex.rb)

Use :

<br/>ruby gethex.rb game1 game2 game3<br/><font face="courier new"><br/>#!/usr/bin/ruby<br/>require 'net/http'<br/><br/>class JHexFormatter<br/>  def formatInt4Pair(key, value)<br/>    return formatKey(key) +<br/>           format4byteInt(4) +<br/>           format4byteInt(value)<br/>  end<br/><br/>  def formatInt1Pair(key, value)<br/>    return formatKey(key) +<br/>           format4byteInt(1) +<br/>           format1byteInt(value)<br/>  end<br/><br/>  def formatStringPair(key, value)<br/>    return formatKey(key) +<br/>           format4byteInt(value.length) +<br/>           value<br/>  end<br/><br/>  def formatKey(key)<br/>    return format1byteInt(key.length) +<br/>           key<br/>  end<br/><br/>  def format4byteInt(value)<br/>    return format2byteInt(value / (2**16)) +<br/>           format2byteInt(value)<br/>  end<br/><br/>  def format2byteInt(value)<br/>    return format1byteInt(value / (2**8)) +<br/>           format1byteInt(value)<br/>  end<br/><br/>  def format1byteInt(value)<br/>    return format("%c", value)  # just the lowest 8 bits<br/>  end<br/><br/>  def formatStandardHexHeader(player1, player2, bdsize)<br/>    header = formatInt4Pair("gtv", 2);<br/><br/><br/>    if player1 != nil<br/>      header += formatStringPair("player1", player1)<br/>    end<br/><br/>    if player2 != nil<br/>      header += formatStringPair("player2", player2)<br/>    end<br/><br/>    header += formatInt1Pair("pov", 0) +      # point of view (0 = alternate)<br/>              formatStringPair("type", "hex1") +<br/>              formatInt4Pair("bdsize", bdsize) +  # adapted from SZ tag<br/>               formatInt4Pair("hgtv", 1) +     # hex game tree version<br/>              format2byteInt(0)<br/><br/>    return header<br/>  end<br/><br/>  def formatMove(move)<br/>    return format2byteInt(1) +   # one node (no tree)<br/>           formatKey("m") +      # m for "move"<br/>           format2byteInt(move.length) +<br/>           move +<br/>           format1byteInt(0)<br/>  end<br/><br/>  def formatCoordinates(x, y)<br/>    return format1byteInt(x - 1) +<br/>           format1byteInt(y - 1)<br/>  end<br/><br/>  def formatSimpleMove(x, y, player)<br/>    return formatCoordinates(x, y) +<br/>           format1byteInt(player)<br/>  end<br/><br/>  def formatShortMove(x, y, player)<br/>    return formatMove(formatSimpleMove(x, y, player))<br/>  end<br/>end<br/><br/>class LittleGolemParser<br/>  def initialize(game)<br/>    @game = game<br/>  end<br/><br/>  def getPlayer1<br/>    p = @game.scan(/PB\[[^\]]*\]/)[0]<br/>    return p[3..(p.length - 2)]<br/>  end<br/><br/>  def getPlayer2<br/>    p = @game.scan(/PW\[[^\]]*\]/)[0]<br/>    return p[3..(p.length - 2)]<br/>  end<br/><br/>  def getSize<br/>    p = @game.scan(/SZ\[[^\]]*\]/)[0]<br/>    return (p[3]-48)*10+p[4]-48<br/>  end<br/><br/>  def getMoves<br/>    moves = @game.scan(/[BW]\[[^\]]*\]/)<br/>  end<br/><br/>  def getWinner<br/>    p = @game.scan(/[BW]\[resign\]/)[0]<br/>    if p == nil<br/>      return nil<br/>    else<br/>      return " BW".index(p[0])<br/>    end<br/>  end<br/><br/>  def forEachMove<br/>    letters=" abcdefghijklmnopqrstuvwx"<br/>    moves = getMoves<br/><br/>    # swap rule<br/>      moves.delete_at(1)  # remove PW player in moves<br/>      moves.delete_at(0)  # remove PB player in moves<br/><br/>    if moves.length > 1 and moves[1] == "B[swap]"<br/>      move = moves[0]<br/>      x = letters.index(move[3])<br/>      y = letters.index(move[2])<br/>      yield x, y, 1       # place red peg first so Jhex doesn't get confused<br/>      yield x, y, 2       # then put black peg right on top of it.<br/>      moves.delete_at(1)  # remove the swap move<br/>      moves.delete_at(0)  # remove the first move<br/>    end<br/><br/>    # the rest of the moves<br/>    for move in moves<br/>      player = " WB".index(move[0])<br/>      if move.length == 5<br/>        x = letters.index(move[2])<br/>        y = letters.index(move[3])<br/>        yield x, y, player<br/>      end<br/>    end<br/>  end<br/>end<br/><br/>def getJhexFileData(lgolem)<br/>    jhex = JHexFormatter.new<br/><br/>    jhexFileData = jhex.formatStandardHexHeader(lgolem.getPlayer1,<br/>                                                 lgolem.getPlayer2,<br/>                           lgolem.getSize)<br/>    lgolem.forEachMove { |x, y, player|<br/>      jhexFileData += jhex.formatShortMove(x, y, player)<br/>    }<br/><br/>    return jhexFileData + jhex.format2byteInt(0)<br/>end<br/><br/>def getGame(httpConnection, gameId)<br/>  directory = "/jsp/game/png.jsp?gid="<br/>  lgResponse, lgData = httpConnection.get(directory + gameId)<br/><br/>  if lgResponse.code == "500"<br/>    print "No such game: ", gameId, "\n"<br/>  elsif lgResponse.code != "200"<br/>    print "HTTP error ", lgResponse.code, " for game: ", gameId, "\n"<br/>  else<br/>    lgolem = LittleGolemParser.new(lgData)<br/><br/>    jhexFileData = getJhexFileData(lgolem)<br/>    jhexFileName = "game" + gameId + ".hgt"<br/>    File.new(jhexFileName, "wb").write(jhexFileData)<br/><br/>    print jhexFileName, ": ",<br/>      "hex",lgolem.getSize,", ",<br/>          (lgolem.getWinner == 1)? "*":"",<br/>          lgolem.getPlayer1, " vs. ",<br/>          (lgolem.getWinner == 2)? "*":"",<br/>          lgolem.getPlayer2, "\n"<br/>  end<br/>end<br/><br/>httpConnection = Net::HTTP::new("www.littlegolem.net", 80, "proxy_IP", proxy_port)<br/><br/>for gameId in ARGV<br/>  getGame(httpConnection, gameId)<br/>end<br/></font>

------------------------------------

If you don't use a proxy just put for "proxy_IP", proxy_port : nil, nil

Ruby for Windows can be downloaded from http://rubyforge.org/frs/?group_id=167

#17 · David J Bush

18 Jan 2008

I tried to follow your instructions, and I modified the line thusly:

httpConnection = Net::HTTP::new("www.littlegolem.net", 80, "proxy_port : nil, nil", proxy_port)

When I ran it I got this error:

gethex.rb:186: undefined local variable or method `proxy_port' for main:Object (NameError)

#18 · David J Bush

18 Jan 2008

Okay I simply used the same line from my Twixt script:

httpConnection = Net::HTTP::new("www.littlegolem.net")

and now it works fine for me! I just downloaded 7 games with one command, from both Hex 13 and Hex 19, some where swap was used, some not, and they all look the same as the LG images!

Thanks Carroll very much for your work!

#19 · Carroll

18 Jan 2008

You are very welcome, thanks for testing!

Yes the line I tested was:

<font face="courier new"><br/><br/>httpConnection = Net::HTTP::new("www.littlegolem.net", 80, nil, nil)<br/></font>

maybe there is a way to test if you are behind a proxy or not and use same skript...

#20 · Carroll

18 Jan 2008

Oh and I forgot to thank and copyright Alan Hensel.

Nice job I just adapted.

#21 · javerberg

22 Jan 2008

If someone have too much free time it would be interesting with all 13x13 hex games played at LG in one single jhex file. :-)

#22 · Marius Halsor

22 Jan 2008

Not all, maybe - but all where both players were above 1700 or so, perhaps...

#23 · Kevin O'Gorman

2 Aug 2008

I just looked at the jhex on sourceforge. It has nothing to do with Kevin Walker's Jhex that most of us know.

Kevin Walker gave me the code base for Jhex and Jtwixt (and fledgling Loa and Reversi versions as well), which I put on sourceforge under a different name.

Look for them as twixhex for now, though a name change to gamerec is pending.

I now regret not reserving the jhex name, but at the time I thought it more

likely that Kevin Walker might want to use it than that some J Random coder would stumble into the name.

Expect future versions to be HexRec and TwixtRec and *Rec, but of course you can rename it to anything you like.

I've been away from it for a while, but the 0.2-alpha version is what I've been using since I released it. There are other changes in the CVS repository, including a LG importer that seems to be working. I'm working on some other changes too, and may have a release soon -- like this summer.

And apropos of javerberg's request, I have a script that got all the games where both players are better than I am, about 4300 games. I used wget for the purpose, not Ruby, because my importer works fine with the raw LG text. The jhex file is at

http://hex.kosmanor.com/hex/golem-080801.hgt

#24 · Dvd Avins

25 Aug 2008

Kevin, what is a .tb2 file? I was relieved to find the hex-only download didn't rely on that type of file, and I guess the twixt-only doesn't, either. But the combined download does and I didn't know how to extract from it.

#25 · ab

25 Aug 2008

.tb2 might be .tar.bzip2

#26 · entr0py

30 Oct 2008

I've made a program which converts a single game from littlegolem to JHex's "simple" format. The program works for both board sizes. But only a single game. The process is this:

1) download a game

2) open it in a text editor, copy it all to your clipboard

3) run my program

The program will automatically open a new Notepad window and paste the converted game. If there was a swap, it will make a comment underneath. You can then save the notepad file and name it what you want.

When you want to view the game in JHex, you must specify "Simple", "Single", and specify the board size (automatic will not work).

You CAN import from the notepad file even if it has the swap comment in it. JHex will ignore the comment.

This is my repayment for the great games you guys have played for me to download =)

It is an .exe file. The source file is an .ahk (written in AutoHotkey).

Send me an email if you want the program and/or its source:

c4filosofer@gmail.com

#27 · entr0py

30 Oct 2008

oh, and if someone knows how to write a swap in jhex format, i could make the program include the swap in the moves instead of as a comment.

#28 · entr0py

30 Oct 2008

2 things have come to my mind:

1) Swap is more important than I first realized, it makes a difference which color edge the first move is near!

2) To specify a swap in JHex, simply repeat the first move twice. For instance: F6 F6

So i've updated my program to convert swaps properly.

#29 · entr0py

30 Oct 2008

I also made a program which doesn't require you to download the game. Simply highlight and copy the list of moves, then run this program. The reason for a separate program is the different format when copying versus downloading.

#30 · entr0py

30 Oct 2008

Actually, this second program works with some other games too, such as Reversi, Go, and Gomoku. And any game which lists its moves like "1.a4 2.p12..." etc.

#31 · Art Duval

13 Feb 2009

I rediscovered entr0py's post here about how to easily implement swap in JHex, which made me so happy.

But...I don't think this works unless the first move is on the long diagonal. For instance: A game starting with 1. a3, which is then swapped puts Blue's first stone (now the first piece of the game) at c1. But if we put A3 A3 into JHex, the Blue stone is still at a3. Of course, if we put A3 C1, JHex leaves Red's stone at c1. Anybody know how to fix this?

#32 · David J Bush

13 Feb 2009

I guess it depends on how you define "easily." the Ruby script shown above allows you to download LG Hex games into JHex file format. The file you get takes care of the swap problem for you. For example 1.a3 2.swap is turned into 1.c1 2.c1. The very first move is shown incorrectly, but the rest of the game is just fine.

If you want to enter a swapped LG game move by move, the GUI won't let you put a token on top of another, but there is a workaround. Use colors different from LG, so it might be less confusing if the color assignment for first player versus second player switches around. Flip the board AND flip the coordinate labels. Now enter the game as though the second player moves first. For example 1.a3 2.swap turns into 1.c1. The colors are switched, and the move numbering differs by 1, but the board display is otherwise the same.

#33 · Art Duval

14 Feb 2009

David: Any sort of script is beyond my understanding (I've tried a couple of times to look at web pages about it, and it just makes no sense to me, even though I know lots of computer programming languages).

But the 1. a3 2. swap turning into 1. c1 2. c1 is absolutely correct. I feel silly for not figuring that out from entr0py's posts, but I am very, very happy to have a way of dealing with swaps that is "easy" for me. Thank you!!

I was trying to avoid the "flip the board" solutions because I don't know how to save that feature to a game (in other words, I can change the colors and flip the board, but when I save the game, and return to it later, the colors are back to normal and the board is unflipped).

#34 · Robert Irvin

6 Dec 2011

A silly question from someone not at all familiar with computer programming: I just downloaded jhex, installed ruby 1.9.3...now what? How do i set it up to use the gethex command?

#35 · maraca

6 Dec 2011

I might be wrong (I never used any program), but just save what Carroll posted as a text file named gethex.rb (the file starts with #!/usr/bin/ruby and ends before the line -------) and then use this command in the console: ruby gethex.rb game1 game2 game3 (probably the ids of the games you want). In windows you can get the console by Start -> run... -> cmd [enter]. If you are using Linux then you should know yourself ;-)

In case you have to switch the partition, just enter C:

To change the directory use cd "directory", to go to the parent directory use cd .. [enter]

#36 · Robert Irvin

7 Dec 2011

I tried this and it returned this error message:

gethex.rb:1:in '': undefined local variable or method 'gethex' for main:Object

#37 · Robert Irvin

7 Dec 2011

well, in brackets it said "main" after gethex.rb:1:in and in brackets it said "NameError at the end. I guess I can't put things in brackets here.

#38 · Robert Irvin

7 Dec 2011

Ok, 2 hours later:

My original error was due to not being able to follow instructions and accidentally including the first line in the file. I've fixed that and manually typed in everything carroll posted. Now I'm getting a "nomethoderror: in line 170 for 'getJhexFileData'. I would surely appreciate it if someone would be willing to just mail me a copy of the file .rb file :-)

#39 · Robert Irvin

15 Dec 2011

Is anyone willing and able to email me a working copy of gethex.rb?