Comments/Ratings for a Single Item
What does Do Not Include Moves in Code do?
Game Courier normally creates a program that includes the moves made by players as lines of code. Checking this will keep it from including the moves in the code, which will keep them from being played automatically. If you check it and do nothing else, you will be unable to move pieces. If you do use it, then you have to write code that will play the moves. This is useful if you want to allow multiple moves, because it allows you to handle one move at a time in a multi-move sequence.
If you were to test the legality of a move before it is made, you would not need the variables that tell you the effects of a move after it has been made. It would also be easier to reuse the same code for both potential and actual moves, and it would make writing code for divergent pieces simpler.
Calculating all legal moves to compare the value returned by thismove with a list of legal moves is really overkill. All you have to do is calculate the legality of the current move. If you test the legality of a move before it is made, you can just get the complete move from thismove and run it through the appropriate tests. This will also allow for some variation in how a move may be entered.
Also, if you want to use the value of a user variable in a command, you need to prepend the variable name with #.
The problem is that it is not always easy to know what exactly one should test. XBetza could allow moves that go through meandering paths to strange destinations, and deducing the path from just the origin and destination square could be problematic. Even with a comparatively simple piece like the Sissa, a move from e4 to g4 could have gone through e5-e6-f5, f5-g6-g5, e3-e2-f3 or f3-g2-g3. With doubly-bent moves (e.g. a Tenjiku Shogi 'area move') it is even worse. The simplest way is often to generate all moves according to the XBetza prescription, and picking out the one that hits the desired destination.
Note that I don't want to generate all moves. Just all moves of one piece. But for that I have to know which piece, and where it starts.
I agree that for simple slides and leaps this might be overkill, and testing those with checkaleap or checkaride (or even checkleap or checkride, if you know the piece to be fully symmetric) would be far simpler. You cannot see from the input move whether that is possible though; the mentioned Sissa move from e4 to g4 looks like a Rook move, but in fact has nothing to do with it. But during interpretation of the XBetza description it can be seen which moves consist of only a single leg. So perhaps the strategy should be to generate direct checks for those (which then for many pieces would handle them completely), and supplement that with a routine to generate all multi-leg moves of a given piece, and only run that to compare these moves to thismove when the simple tests have failed.
But this is basically optimalization. The point is that a routine to generate all moves (even not just of one piece, but of all pieces) is needed anyway, for the purpose of setlegal. Once that function exists, it is trivial codewise (albeit a bit inefficient timewise) to use it to compare the moves with the input move. The best strategy for getting something that works seems to start with the codewise simple method. Once that works it can be optimized by generating dedicated code for some of its tasks.
Note that I don't want to generate all moves. Just all moves of one piece. But for that I have to know which piece, and where it starts.
You can get that information yourself. Just play each move under program control, then store the information after each move. Alternately, you can evaluate a move before making it, and the information you need to evaluate it will be on the board.
Even with a comparatively simple piece like the Sissa, a move from e4 to g4 could have gone through e5-e6-f5, f5-g6-g5, e3-e2-f3 or f3-g2-g3.
A Sissa is not a good example in support of what you want to do. All a Sissa function has to do is determine whether there is a path it may legally take to its destination. This can be done without calculating all possible moves for that piece. Besides that, the player would just enter the origin and destination of the piece, not the path that it takes. So, generating paths to compare with the move entered by the player wouldn't work.
The point is that a routine to generate all moves (even not just of one piece, but of all pieces) is needed anyway, for the purpose of setlegal.
Because this is used to check for checkmate and stalemate, it has to be run after the move has been played. You're proposing doing it an additional time. Moreover, it doesn't have to generate detailed information about each move. It just has to cover the first move a piece may make in a sequence of moves. When extra moves have to be entered for a piece, the continuemove command can be used, as it is in Extra Move Chess. But this presumes that you are handling moves one-by-one and not letting them play all at once.
Would it be an idea to tick the checkbox and take charge of the parsing of the move ourselves? E.g. with code like:
set mvs explode chr 59 thismove; set parts explode ws trim elem 0 mvs; set i count mvs; if > i 2: die "move must be piece ID plus board step"; endif; set sqrs explode chr 45 trim elem dec var i parts; if != 2 count sqrs: die "board step does not mention two squares"; endif; set myorigin elem 0 sqrs; set mydest elem 1 sqrs if not onboard myorigin or not onboard mydest: die "the board isn't that large"; endif; set mymoved space myorigin; if != mymoved elem 0 parts and == 1 i: die join "there is no " elem 0 parts " at " myorigin; endif;
This seems more efficient than storing and restoring the game state all the time to undo what the system does automatically. And it could also be extended to understand more elaborate move formats, like origin-ep-dest or even origin-ep1-ep2-dest for moves that make a locust captures on ep / ep1 / ep2. Of course we would have to make the move ourselves, at some point, (after the legality testing) by something like
empty myorigin; capture mydest; add mymoved mydest;
A general question: do the logical operators and and or also accept numbers as operands, and do they consider 0 false and any other value true, like in C? Or do I explicitly have to convert them to logical values by comparing the numbers with 0?
And am I correct in assuming there is a distinction between using inc (or empty) as an operator in an expression or as an independent command, where only in the latter case it alters its argument? (I.e. is let a inc var a; the same as inc a; ?)
Would it be an idea to tick the checkbox and take charge of the parsing of the move ourselves?
Yes, you could do that. But bear in mind that any move with three or more elements must be entered by hand. Game Courier passes legal moves to JavaScript as pairs of coordinates, because when players move by clicking the mouse or tapping the screen, it interprets two clicks or taps on different spaces as a complete move and immediately submits it as the move. It keeps the interface more user-friendly when players are able to move by mouse click or screen tap.
Of course we would have to make the move ourselves, at some point, (after the legality testing) by something like
empty myorigin; capture mydest; add mymoved mydest;
Moves entered by players should normally be processed with the MOVE: command. This name is case sensitive and includes the colon. It should not be confused with the move command. However, the MOVE: command expects no more than two coordinates to a move. If you bypass it, you will also be bypassing the benefits of banning types of input, and you would have to handle all bad input on your own.
Once again, I see you referring to variables simply by name. This works only when assigning a value to a variable. When you want to access the value of the variable, you need to prepend it with #, or, if you need the value in an expression, precede the variable name with the var keyword. These work differently. #myorigin would replace the string "#myorigin" with the value of myorigin while preprocessing the line. This is useful for commands that do not evaluate expressions. In an expression, var myorigin would return the current value of myorigin each time it evaluates the expression. This is useful in functions, which normally need the most up-to-date value of a variable. Using #myorigin in a function definition would insert the then-current value of myorigin into the function, and it would continue to use that value even if the value of myorigin later changed.
A general question: do the logical operators and and or also accept numbers as operands, and do they consider 0 false and any other value true, like in C?
Yes, GAME Code is written in PHP, which is written in C. So, in inherits some features of its grandparent language. Like in PHP, which is its parent language, variables are untyped. So, any empty, zero, or null value is false, and any non-false value is true.
And am I correct in assuming there is a distinction between using inc (or empty) as an operator in an expression or as an independent command, where only in the latter case it alters its argument?
Yes, that's correct. Commands may change the values of variables, but operators in expressions just return values without changing them.
is let a inc var a; the same as inc a; ?
let is not a command in GAME Code. You want to use set. With that change, yes, though using the inc command will be more efficient.
OK, thanks. I never used PHP, so it takes a bit of getting used to. The 'let' must have been a sub-conscious confusion with BASIC. What also confuses me is that the # / var do not seem to be needed on origin, dest and such. Is that because these are really subroutines rather than variables?
The need to handle the implied side effects is a bit of a pain. XBetza could potentially define e.p. capture through Gryphon or Sissa moves. Also, to test the pseudo-legality of the latest move of the game, the preceding move would have to correctly set the e.p. rights. The best strategy seems to include a 'stripped' move generator in the GAME code, which generates only moves with implied side effects (i.e. e.p. capture, moves that create e.p. rights, and castlings). This would then be run for every simple move (the mentioned moves are never composit). This would be rather cheap, as most pieces don't have any such moves at all, so it would not generate anything when these move. In most CVs it would only generate something when a Pawn or a King moves, and it would then only generate the double-push if it was a 2nd-rank Pawn, the e.p. capture if an e.p. square was created on the previous move, and in range, and sometimes one or two castlings. The few moves it generates could then be compared to origin and dest, and if one of them matches, all the side effects of it indicated by the move generator (i.e. e.p.-victim removal, Rook movement, or setting of the e.p. rights) would then be applied to the board.
For the latest move a complete move generator would generate all moves of the moved piece, and compare those to the input move. This is not optimally efficient, but it is easy and requires very little code that wasn't needed already for other purposes. And it is still very much cheaper than generating all legal moves in the final position for the purpose of setlegal: it has to be done only for a single piece, and the full legality has to be tested only for the move that matches the input. While setlegal requires the pseudo-legal moves of all pieces, and has to test each and everyone of those for legality. So there really wouldn't be any significant gain in optimizing it further, just a far larger code complexity.
What also confuses me is that the # / var do not seem to be needed on origin, dest and such. Is that because these are really subroutines rather than variables?
These are early system variables that I made available before I started making system variables available with $ prepended to them. You can now access them as $origin, $dest, and so on. If I had to do it over, you would not be able to use them just by name, but if I changed it now, it would break lots of code. I recommend using them with $, because that makes it clearer that they are variables.
Just to be sure: lines in subroutines are only 'pre-processed' when they are executed, but functions when they are defined? So in subroutines var and # would be equivalent?
I slowly start to converge on a design. The idea is that the Post-Move code would always only contain only the line gosub HandleMove false; (for white) or gosub HandleMove true; (for black). Similarly, the Post-Game code would only contain gosub GameEnd true/false; . The routines would be universally applicable code, which could go into the Pre-Game section, or into a file that would be included from there.
The rules would then be described in the Pre-Game section by a large initialized array 'legdefs' of integer numbers, encoding all the moves, functions for each piece type returning where the move data for that piece type starts in legdefs. Plus statements to set a number of parameters, like what the royal type for each player is, whether stalemate is a win or draw, what King destinations imply castling, where the castling partners are located, how large the promotion zone is, what you can promote to on various ranks, which pieces van promote and stuff like that. Defaults for those parameters could be set in the included file, but the CV-specific code could overrule those settings after the include. It is this Pre-Game code that would be generated by the Play-Test Applet.
A rough draft of the code for such a design is this:
// the following arrays and functions are variant-specific, and would be defined in Pre-Game: set legdefs (....); // a (very large) array of numbers, describing the moves of all pieces // each move is a sequence of 'legs' (leaps or slides in one direction) // each leg is described by 4 numbers in legdef: // range, sideway step, forward step and 'mode'. // the mode packs bit flags describing what must be at the end of the leg // a move with 0 legs is used to indicates the list for that piece ends def P cond #0 223 45; // functions map piece types on their move definition in legdefs def p cond #0 235 70; // each piece has two move definitions: e.p.&castling-only, or all their moves def K ... set many wroyal K broyal k; ... // the following code is generic, and can be handled as a Pre-Game include sub GotMove orisqr destsqr: // process the move specified by the params and the globals like locustsqr if == 0 #task: // apply side effects of a matching move verify == #orisqr origin and == #destsqr dest: if #locustsqr: empty locustsqr; endif; if #dropsqr: add #unload #dropsqr; set hit true; // abort further generation elseif == 1 #task: // test input move for pseudo-legality verify == #orisqr origin and == #destsqr dest: if not #implied: // explicitly specified side effects must also match verify == #locustsqr #suicide; verify == #dropsqr #freedrop; verify == #unload #dropped or not #dropsqr; else: // no side effects must be specified when they are implied verify not #suicide and not #freedrop; endif; set hit true; // we found a matching pseudo-legal move elseif == 2 #task: // accumulate all pseudo-legal moves setlegal #orisqr #destsqr; elseif == 3 #task: // test whether move captures king (for check test) if == #royal space #destsqr: set hit true; elseif #locustsqr: set hit == #royal space #locustsqr; endif; elseif == 4 #task: // find one legal move (for mate test) my victim locustvictim; set victim space #destsqr; // save old values // make the move if #locustsqr: set locustvictim space locustsqr; endif; if #dropsqr: add #unload #dropsqr; endif; move #orisqr #destsqr; // test whether in check gosub InCheck #side; // unmake the move move #destsqr #orisqr; if #dropsqr: empty dropsqr; endif; if #locustsqr: add #locustvictim #locustsqr; endif; set hit not #hit; // continue when in check, stop when not endif; endsub; sub NextLeg togo legindex startsqr cursqr iso: // this routine is the heart of the move generator // it generates the destinations of one leg, // and then calls itsef recursively for the remaining legs // 'togo' tells how much legs still have to be done; when 0 we have a complete move // 'legindex' tells where the leg descriptions start in the 'legdefs' array // 'startsqr' is where the piece that must make the move starts // 'cursqr' is where any previous legs brought us // 'iso' is the number of leaps taken in an earlier riding leg if #togo: // move not complete yet; attempt next leg my range dx dy mode to; // retrieve leg description (next 4 elements in 'legdefs') set range elem #legindex #legdefs; set dx elem + 1 #legindex #legdefs; set dy elem + 2 #legindex #legdefs; set mode elem + 3 #legindex #legdefs; if & #mode i_FLAG: // initial move only verify not ?startsqr; // suppres it for non-virgin piece endif; // simple example, handling only (divergent) leaps if == 1 #range: // leg is leap set to where #cursqr #dx #dy; // calculate destination set victim space #to; // look what is there verify != void #victim: // abort if off board if == @ #victim: // empty target if match #to #epsqrs and & mode e_FLAG: // move is valid e.p. capture set locustsqr #ep; // flag that it will capture last mover set implied true; // this is an implied side effect else: verify & #mode m_FLAG; // m_FLAG etc. are in fact hard-coded constants like 1, 2, 4, 8... endif; elseif != #side islower #victim: // foe verify & #mode c_FLAG; else: // must be friend verify & #mode d_FLAG; set unload #victim; // remember what we 'captured'. endif; gosub NextLeg dec #togo + 4 #legindex #startsqr #to #iso; // do nex leg else: // leg is slide ... endif; else: // move finished successfully; process it GotMove #startsqr #cursqr; endif; endsub; sub GenMoves piece sqr all: // generates moves for 'piece' on 'sqr' in current position // 'all' specifies whether we get only moves with side effects my index legcount; set side islower #piece; // remember which side we are generating for set index fn #piece #all; // function returns start of piece description in legdefs table do: set legcount elem #index legdefs; // the first element specifies the number of legs verify #legcount; // a 0 sentinel ends the list of moves inc #index; // 'reads away' the leg count set many locustsqr 0 dropsqr 0; // default is no locust capture or unload set implied 0; // generated e.p. or castlings set this gosub NextLeg #legcount #index #sqr #sqr 0; set index + #index * 4 #legcount; // skip to the next set of legs (= move) loop until hit; endsub; sub GenAll black: if #black: def friends onlylower; else: def friends onlyupper; endif; for (from piece) fn friends; gosub GenMoves #piece #from 1; next; endsub; sub HandleMove player: gosub ParseMove thismove; // this extracts origin, dest, moved, suicide, freedrop, dropped set hit false; if == mln $maxmln: set task 1; // request legality test gosub GenMoves moved origin 1; // match all moves if not #hit: die "a " moved " cannot move that way!"; endif; endif; set task 0; // request execution of implied side effects gosub GenMoves moved origin 0; // only tries e.p. and castling eval join "MOVE: " thismove; // make the move setflag dest; endsub; sub InCheck player set task 3; // request king-capture test set hit false; set royal cond #player #broyal #wroyal; gosub GenAll not #player; endsub; sub GameEnd player: gosub InCheck player; if #hit: die "that move would put you in check!" endif; set task 4; // request one legal move gosub GenAll not player; if not #hit: // could not find one gosub InCheck not player; if #hit: // checkmate! won; elseif #staledraw: // stalemate draw; else: won; endif; endif; ... // draw stuff endsub;
Below is how the GAME code generated for the Pre-Game would have to look for orthodox Chess. This assumes 'smart' generation, which realizes that most pieces are symmetric, so that white and black can use the same table entries for those, and that the Bishop is just the final part of the Queen. Most likely it would be too dumb to see the latter, and then a separate Bishop section would be added. If the pieces were asymmetric, or it was not smart enough to realize they are symmetric, all pieces sections would have to appear in duplicat: one for white, one for black.
include betza.txt set legdefs 1 1 0 1 3 // King (0) 1 1 0 -1 3 // 3 = m_FLAG + c_FLAG 1 1 1 0 3 1 1 -1 0 3 1 1 1 1 3 1 1 1 -1 3 1 1 -1 1 3 1 1 -1 -1 3 2 9 1 0 8 // castling (40) 1 2 0 3 2 9 -1 0 8 1 -2 0 3 0 1 9 0 1 3 // Queen (59) 1 9 0 -1 3 1 9 1 0 3 1 9 -1 0 3 1 9 1 1 3 // Bishop (79) 1 9 1 -1 3 1 9 -1 1 3 1 9 -1 -1 3 0 1 9 0 1 3 // Rook (100) 1 9 0 -1 3 1 9 1 0 3 1 9 -1 0 3 0 1 1 2 1 3 // Knight (121) 1 1 2 -1 3 1 1 1 2 3 1 1 -1 2 3 1 1 -2 1 3 1 1 -2 -1 3 1 1 1 -2 3 1 1 -1 -2 3 0 1 1 0 1 1 // white Pawn (162), 1 = m_FLAG 1 1 1 1 2 // 2 = c_FLAG 1 1 -1 1 2 1 1 1 1 4 // e.p. capture (177), 4 = e_FLAG 1 1 -1 1 4 2 1 0 1 577 // double push, 577 = m_FLAG + i_FLAG + rights creation 1 0 1 1 0 1 1 0 -1 1 // black Pawn (197) 1 1 1 -1 2 1 1 -1 -1 2 1 1 1 -1 4 // e.p. capture (212) 1 1 -1 -1 4 2 1 0 -1 577 1 0 -1 1 0; def K cond #0 0 40; def k cond #0 0 40; def Q cond #0 59 58; // 58 = empty move set def q cond #0 59 58; def R cond #0 100 58; def r cond #0 100 58; def B cond #0 79 58; def b cond #0 79 58; def N cond #0 121 58; def n cond #0 121 58; def P cond #0 162 177; def p cond #0 197 212; set pzs 1; // promo zone depth set rooks a1 a8 h1 h8; // castling partners set wchoice (Q R B N); set bchoice (q r b n); set stalemate 1; set wroyal K; set broyal k;
Game Courier offers two ways of evaluating moves. I usually default to using the mathematical functions, which treat the board as a grid whose spaces have mathematical relations to each other. But I have also provided functions for logical evaluations of moves. These represent the board through logical relations between spaces rather than mathematical relations. To use these, you define various directions in terms of which space you will go to if you move in that direction from a particular space. Using these may fit better with how you are trying to go about evaluating piece movement. See the Programming Piece Movement in Game Courier tutorial for more about this.
Well, this is definitely a powerful method, and allows handling of boards of any topology. But I don't see how it would simplify things in this case. The Interactive Diagram can only handle grid boards consisting of squares. Perhaps with some straightforward wrapping rules (periodic boundary conditions, such as cylinder or torus). Betza notation would be meaningless in boards with irregular topologies.
The code example doesn't alllow for wrapping yet. I guess that when the where operator produces an off-board result, it should really test mode to see whether the move is supposed to wrap (o_FLAG). If it does I guess I would be in for some cumbersome arithmetic on separate file and rank of the startsqr. That would also mean that I cannot use ray for the riding legs, but would somehow have to extend the ray after wrapping.
I wasn't suggesting it for use with unusual topologies. I'm thinking it could make it easier for a program to translate Betza code into finetune distinctions using logical directions rather than mathematical relations.
It is true that XBetza uses directions and relative directions a lot. But the Diagram script already translates that to absolute grid vectors in a compilation step. The legdefs array is almost exactly what the Diagram uses as internal representation (except that dx, dy, range and mode there each have their own array, but that is a minor detail). So the only thing it has to do when someone would hit the would-be button 'Show GAME code' would be to dump those tables for the pieces that were chosen to participate in the desired format, and remember where the data for each piece started. It can be easily checked during the Betza-to-table compilation whether a piece is totally symmetric. (Not done yet; the Diagram only makes tables for white pieces during the compilation, and when it later generates moves for black pieces, it just flips the sign of all step vectors it retrieves from the table. But it seems faster to tabulate the black pieces separately, flipping their steps already in the table, if they were asymmetric.)
Configuring the applet to play test my variant called Cetran Chess 3, I find that something is wrong after inserting the HTML code on a web page because images of certain pieces are not uploaded. Five are the ones that fail: Amazon, Marshall, Archbishop, Knight-Wazir and Knight-Ferz.
Regardless of this small inconvenience, I can not but congratulate you for having developed such an extraordinary applet and I hope it is not complicated to fix the problem.
Umm, there seems to be a mismatch between the naming of the scalable (SVG) pieces used in the Applet, and the fixed-size 50x50 (GIF) bitmaps in the alfaerie directory. E.g. the wazirknight does not show up because for the alfaerie bitmaps it is actually called knightwazir. The Archbishop / Chancellor / Amazon are my own fault; the SVG renderer used by the Applet creates such compound images 'on the fly', by referring to them as knight--bishop, knight--rook and knight--queen, while in the 50x50 alfaerie set they are of course called cardinal, chancellor and amazon. I should have had the Applet script replace those names when it dumps the design as a diagram using the standard image set.
Thank you for reporting this; it will certainly be fixed one way or the other. For now you can work around it by editing the Diagram description to replace the faulty filenames of the missing pieces by the correct ones. An alternative would be to keep the names, but change the graphicsDir from /graphics.dir/alfaerie/ to http://winboard.nl/my-cgi/fen2.cgi?s=50&p= and the graphicsType to an empty string (just graphicsType= ), to get the same anti-aliased images as the Applet uses (but 50x50). But then you would be using off-site images, and that is really against CVP policy.
For the editors:
In connection with this, it is perhaps a good time to bring up the following issue: wouldn't it be a good idea to improve the availability and/or quality of piece graphics on CVP? The rather ragged-looking alfaerie 50x50 GIF bitmaps in /graphics.dir/alfaerie/ are still the site's standard piece set. Isn't it time to replace those with anti-aliased PNG images, or at the very least provide such a set next to it (e.g. in /graphics.dir/alfaeriePGN/)? I suppose it would be easy to copy the same index page on alfaerie to that other directory, to showcase the pieces.
I would also be happy if there could be a 35x35 alfaerie image set; for the Applet I am currently using an off-site SVG renderer. Of course I could upload a set of 35x35 images myself, even defvote a member-submitted article to them, but then they would be hidden in /membergraphics/MSalfaerie-33 (say), and no other person but me would ever find them there. To get good use of the graphics we have, they really should be provided as options in places where people could decide to use them.
I think changing over to anti-aliased pieces is certainly a good idea and it is something that I have wanted to do for quite a while, but it is a large undertaking. The Alfaerie set is huge, but even getting the most common pieces would be worthwhile. It is unlikely we'd ever get them all converted. I know you have done a lot of work converting Alfaerie images to SVG already. I did some work converting the Abstract pieces but stopped, although I am happy to resume. I want to upgrade the graphics in ChessV as well.
I do not want to replace existing images - I think we make a /graphics.dir/alfaeriePGN/ and /graphics.dir/alfaeriePGN35/ and fill them with upgrade images as they become available. I don't want to replace the existing ones because, for my games at least, I would not want to mix-and-match. I would only switch over to anti-aliased graphics if they were available for all the pieces I was using.
Okay, no rush. While fixing the issue, I'm using this other setup which is very useful to study the tactical possibilities that Sissa offers within the context of standard chess when replacing Queen for Sissa.
It should now be fixed for new Diagrams generated by the Applet. But it might still be easier to just edit the image names in the Diagram you already made than redoing it from scratch. While fixing the issue I was baffled by the fact that the Applet had stopped working completely; its board mysteriously disappeared. After a lot of debugging it turned out that it was upset that another Diagram had appeared on the same page, in the Comments. The Applet needed to change some settings after initialization, but the way I had programmed that was not resistent to the betza.js file being read a second time, undoing some of the changes. I guess it was a very bad idea to have some of the standard initialization code execute unconditionally when the script gets loaded, in a script that could be loaded multiple times. Eventually I modified the script such that custom post-initialization code can be executed after all Diagrams on the page have done their initialization, rather than just the first one.
I also made the Applet close the ad side bars when the board has more than 10 files. This should prevent the compression we see in the screenshot you posted.
BTW, I noticed that you are using piece IDs of more than one letter. The Diagram was not really designed for that. In particular, it confuses its detection of which promotions are allowed. Because you use both K and DK, and put DK amongst the promotion choices, it now thinks K is also an allowed choice, because there is a K in DK. I am not sure how this can be cured without breaking already existing diagrams.
@Greg:
OTOH, having one or two ugly pieces among good-looking ones would provide a really good incentive for creating the missing SVG. :-) The variants you authored do not seem to feature that many pieces for which we have no SVG yet.
Where can I download the latest set of SVGs?
You already put those on this website, at /graphics.dir/svg/ . I haven't made any new ones since then, as it seemed not much was happening with them, and almost everything that I imagined I would ever need was already done.
There is an identical set on the winboard.nl server, where I have the SVG renderer as CGI program. I use them in the Diagram of the Applet through that renderer, but the Applet first looks in the /graphics.dir/svg/ directory on CVP to see what pieces exist. (Browsers do not allow peeking at a website other than where the main HTML page comes from.) The piece table of the Applet contains everything that is there, plus some compounds that the renderer creates on the fly.
There are no SVG for these compounds (or for rotated pieces, or red / green pieces), but since the renderer can supply all those as PGN it should not be too difficult to download those one by one and put them in the PGN sets.
Ok, I opened wqueen.svg with Inkscape and was able to save it as a 50x50 PNG with no problems. But making the black piece isn't working quite right. The object "inside" the path doesn't go all the way to the edges so when I change the fill color there is still a thin white border. Am I doing something wrong or do I need to edit this shape? Or should I not be using Inkscape at all but your online renderer?
25 comments displayed
Permalink to the exact comments currently displayed.
If the info on the first move on the sequence was always available, e.g. as firstmoves, firstorigin etc., and we would use the checkbox to suppress autoexecution of the move, it might be acceptably efficient to do the legality checking on all moves. That would certainly simplify the code a lot:
Post-Move:
The need to store / restore has disappeared. The subroutine genmoves compares the moves of the moved piece in the pre-move position stringwise with thismove, and detects the cases where we are dealing with castling and regular e.p. capture. The implied side effects of these are then flagged by setting unload, dropsqr and locustsqr (which otherwise remain at false). Non-implied side effects are explicitly specified by the move, and thus already executed when we make thismove. So only these implied side effects have to be made afterwards (if the move proved pseudo-legal).
The subroutine genmoves would handle testing and setting of the e.p. info by itself; global variables ep and epsqrs would be involved in that.
Because the code is color-independent, it would probably be best to put it in a subroutine, and have both Post-Move sections just call that subroutine. Since it is also not dependent on the specifics of the variant, it could even be put in an include file. If the routine genmoves would be 'table-driven', it would also be variant-independent, and could also go into that include file. The data to drive it could then be supplied by variant-specific functions for each piece that would return an array describing the moves they could make. It would be the definitions of these funcions that would be generated by the Play-Test Applet, and would have to be copy-pasted to the corresponding preset. (To the Pre-Game section?)
I suppose the info about the first move of the sequence could be extracted 'by hand', by repeated explode, fist on a semicolon, then on a space to separate piece ID from move (already providing moved), and finally the move part on hyphen to get origin and dest.