LuaTahi
Pages: 1 2
Stephan Kleinert (2271) 70 posts |
Having decided to put my money where my mouth is, here’s a little card game I wrote 3 years ago in RiscLua…: http://code.stephan-kleinert.de/riscos/LuaTahi.zip LuaTahi (or tahi for short) is a “uno”-style card game where you play matching numbers or colours, along with a few wildcards (“ø” is for skip, “++” is for skip and opponent takes one card, “W” is for new colour, and “W4” is for new colour and opponent takes 4 cards). From a technical perspective, you might find it interesting that LuaTahi uses a “FontWriter” module, which I wrote for a completely different project to provide an easy-to-use interface to RISC OS’ font capabilities. As you can see, it’s one of those things that at least got 95% finished. Tahi still could do with a nice Icon and proper cards… and it would be nice to WIMPify it. But it’s released under MIT license… so if anyone feels motivated, go ahead. p.s.: This one comes with its own embedded rlua5 binary & libs, because rlua6 breaks it, and rlua7 breaks it even more. Oh well ;) p.p.s: If you liked this, there’s way more RISC OS stuff gathering dust on my hard drive… |
Glen Walker (2585) 469 posts |
Yes please! I probably have some space on one of my websites if you wanted somewhere to host it all? |
Kevin (224) 322 posts |
It’s a nice game |
Willard Goosey (5119) 257 posts |
A neat little game… Maybe a little more about the rules? It’s apparently good to get Tahi but what exactly is it? |
Fred Graute (114) 645 posts |
Which version of RISC OS are you using? More specifically, which version of WindowManager? Both rlua6 and rlua7 use VFP and require at least WindowManager 5.60 (17-02-2018) which has a bug fixed relating to switching VFP contexts. |
Stephan Kleinert (2271) 70 posts |
Thanks for the hint, but I’ve already figured out the problem. I wrote a module called ‘FontWriter’ for easy font handling. FontWriter relies on integer arithmetic and gets confused when presented with rlua6/7’s floating point arithmetic. Also the function that draws the card shapes was written with integer in mind. This would be easy enough to fix, but then the whole thing wouldn’t run on my StrongARM RiscPC any more (because rlua6/7’s dependence on ARM7+ hardware). So I figured the most sensible thing to do is to stick with rlua5 and provide it along with the game (and hope that someday Gavin will come along with a version of RiscLua that runs on the RiscPC again ;-)) |
Stephan Kleinert (2271) 70 posts |
Thank you :)) “Tahi” is simply the state when you have only one card left. In Uno (after which Tahi is modelled), it’s customary to shout ‘Uno’ when you have one card left, so I figured Tahi needs this, too ;) |
GavinWraith (26) 1563 posts |
It is Lua 5.2.2 compiled with Norcroft, with the “riscos” library built in and 32-bit integer numbers, update operators ( + = etc) and the local varlist in table-expression statement. No floats, no lpeg. It is a long time since I had a RiscPC so it has not been tested. I should be able to serve up virtually any past version. I have kept an archive and so can send you copies. What I have not kept, I am afraid, are the contemporary versions of the tools they were built with, as they would not run on my Rpi3 anyway. But presuming that the Acorn C/C++ DDE27 will produce code that runs on the RiscPC I can cook up any feasible version you want. |
Stephan Kleinert (2271) 70 posts |
Thank you :) All is well, I have these past versions. What I meant to say: With rlua6 and rlua7, you introduced some incompatibilities which cause problems with some small diversions of mine. Which is not a big deal. The crashes in LuaTahi for example would be easy to fix by (among other things) exchanging the division operator (“/”) with the integer division operator (“//”), and exchanging the rlua5 xor operator (^^) with the rlua6 xor operator (~). But then it wouldn’t run with rlua5 (and, hence, the RiscPC) any more. It’s really a minor problem. It’s just that I like my old RiscPC and I like optimizing things on it… because you know, optimizing code on a slow machine can be quite rewarding ;) The best thing really would be a rlua7 which doesn’t need hardfloats. But I realize that’s too much to ask for as it would solely satisfy my somewhat perverse need to have things running on some ancient hardware ;-) So long story short, everything’s fine, as long as I can bundle rlua5 with my programs. |
GavinWraith (26) 1563 posts |
Of course. You can also use the utilities to make standalone executables.
In February 2004, when RiscLua was a module rather than an application, I made a special version for Harriet Bazley; I cannot remember now the details why she needed it. So a request for a special is by no means too much.:) Does stuff compiled with GCC (v 4.7.4) run on the RiscPC? GCC provides quite a bit of choice when it comes to code generation. |
Rick Murray (539) 13851 posts |
Can I have one with extra pickles, please? ☺
? Can’t you ‘cast’ the new-Lua floating point numbers into integers to pass into your font code? Don’t the function definitions contain an explicit type? |
Stephan Kleinert (2271) 70 posts |
(Gavin, correct me if I’m wrong…) There’s no integer data type in lua per se. When you divide two integers with the integer division operator (//) you get an integer as result, otherwise (/) you get a float. And that’s all fine so far, but risclua5 didn’t have the integer division operator, as everything was an integer division. What I could do is programatically determine which version of Lua is running and then do the one thing or the other ;) |
GavinWraith (26) 1563 posts |
That is right. In the early days of Lua both integers and floats were conflated simply as numbers , presumably because this was thought to be a kindness to clueless users. There were also coercions between strings and numbers. Unless I am mistaken, the mood is changing: typing is seen to be a good thing, coercion bad. Lua is nevertheless rather conservative. Internally Lua makes the distinction LUA_INT_TYPE and LUA_FLOAT_TYPE (see the source file luaconf.h in which you can configure a wide range of possibilities). In early versions of Lua only tables and userdata could have metatables. Now everything can have a metatable. There has been discussion of extending the metatable feature to provide a fuller range of types. My personal attitude is that the pretence that integers and floats are both numbers is an ugly troublesome kludge, and not worth the effort. It would be an interesting exercise to go through the Lua sources with an eye to recasting them with distinct integer and float types. |
Steffen Huber (91) 1953 posts |
I couldn’t quite believe what I read here and decided to investigate. Basically, it is a mess. The official Lua tutorial says “Lua has no integer type, as it does not need it” which is as frightening as it sounds because the then following reasoning is something between wrong and incomplete. And I don’t understand how Lua can actually call C libraries without at least supporting a sensible subset of the (already very incomplete) C type system. If I understood the RiscLua situation correctly, RiscLua up to and including version 5 uses ints for everything (why not long as suggested by the Lua tutorial?). Again, I don’t understand the reasoning. Having no hardware FP may be detrimental to language performance that treats every number as double precision float, but using int instead sounds like a bad decision. And if someone cared for performance in numbercrunching, they wouldn’t use a scripting language anyway. And by the way, the Wikipedia RiscLua article (and I am deeply impressed that they let that one through, after seeing quite a lot of articles vanish because of “not of encyclopaedic interest”) links to http://lua.riscos.org.uk/ which seems to be dead. And the RiscLua link from http://lua-users.org/wiki/RiscLua ends in an empty page. My last word: any programming language that does not at least provide separate types for decimal (fixed point) and floating point numbers should be considered “broken by design”. |
Rick Murray (539) 13851 posts |
Fully agree. Integers and reals are indeed numbers but they are numbers in the same way that apples and oranges are fruit. They are different things, they serve different purposes, and – my God – even BBC BASIC version 1 made a distinction between the two… |
Stephan Kleinert (2271) 70 posts |
I agree that the number situation in Lua is unsatisfactory to say the least. But Lua tables on the other hand are a godsend. A facility to quickly and effortlessly build dictionaries OR arrays OR sets OR switch-case-structures OR classes and instances, all out of one single and easy to use data type is something that makes Lua very, very appealing. To me, at least. Of course, your mileage may vary, and to each his own ;) |
Peter Scheele (2290) 178 posts |
You see the same thing in Python. And from Python I learned that it needs a complete different way to look at it. It is important to understand that variables in Python are really just references to objects in memory. So, instead of assigning a value to a name (and prepare the name for that value with %, $ etc), you have a value in memory you assign a name to. Whatever value and whatever name. In your program you have to figure out what that value is and what you can do with it. Certainly, it is difficult, not easy to understand. It needs a different way of thinking. But to call that “broken by design”… |
GavinWraith (26) 1563 posts |
This is possible because of Lua’s very clever interface with C. You might enjoy reading about this in section 27.2 of the book .
Because RISC OS, and SWIs, expect 32-bit integers. In the early days of RiscLua my primary concern was how to implement something analogous to BASIC’s SYS. In actual fact RiscLua 6 used 64-bit integers. In those circumstances you have to be aware that when the RISC OS PRMs talk about using -1 as a value they mean 0xffffffff and not 0xffffffffffffffff. I was aware that RiscLua users might prefer not to be restricted to 32-bit integers, and I went through a variety of contortions to provide them with a wider choice of number: doubles realized in the heap, arbitrary size fixed-point bignums, the mapm and the bc libraries, … . All of these were unfortunately afterthoughts, tacked on as extra libraries. I agree with the broken by design comments. I have just sent a suggestion to lua-l@lists.lua.org:
|
Willard Goosey (5119) 257 posts |
Ah so! Thank you. :-) |
Steffen Huber (91) 1953 posts |
I notice that you immediately jumped from my original point “decimal vs. floating point” to “integer vs. real”. Probably the mental imprint of BBC BASIC and C :-) I think there are two possible ways to handle that “number” stuff. Either you completely abstract from the CPU’s representation and guarantee a certain precision for all operations on the one “number” type. Nice for the user, but slow. Or you provide a rich type system of integer, decimal, float with user-defined precisions and clear rules how that is mapped to the CPU’s representations and operations. |
Rick Murray (539) 13851 posts |
That’s because “real” encompasses floating point without lending itself to any implementation defined assumptions.
I think it’s BASIC that calls them real. C refers to float, double, and long double (because it’s generally more closely related to the IEEE definitions; though in Norcroft double==long double).
This is what C generally tries to do. For most contemporary non-weird hardware, a “float” and a “double” should be the same things – that is to say a float being a four byte representation and a double being an eight byte representation. These are supposed to map to the IEEE single (4 byte) and double (8 byte) types as defined by IEEE 754-1985. For integers, a char is eight bit, a short is 16 bit, a long is 32 bit, a long long (if implemented) is 64 bit. The anomaly here is int which is generally supposed to be equal to either a short or a long as depending upon the native word size of the processor. In compilers such as TurboC where the x86 was used in 16 bit mode, int is 16 bit, whereas on RISC OS where the ARM is a 32 bit processor, int has always been 32 bit. How C does it “works” (on many systems) because of the inherent similarities in how numbers are dealt with. There may be some additional hoops to jump through (like dealing with 16 bit values on the ARM 2 or dealing with 32 bit values on a Z80 but this isn’t impossible and is usually just a few instructions extra emitted by the compiler). Compare this with a “value” which is defined less by what it is and more by how it is used. Is it a float? Is it an integer? Who knows! It can “be” as it needs to be. I’m sure that’s great for Buddhist philosophy, but to my mind it is bloody awful for programming. A rich set of variable types exist so the programmer can choose the appropriate type for the job. There’s an on-screen “lives” counter. You have five lives. When this counter reaches zero, it’s hasta-la-vista-baby. The best type for that is int (processor native word size). The worst type for that is any sort of floating point… it’s just inefficient. |
Steffen Huber (91) 1953 posts |
This was not my point. I did not say anything about integers, you did the “conversion” from decimal to integer. Which completely misses my point.
“Tries” being the operative word here. C has a lot of “implementation defined” in the standard. C99 and C11 added a lot of detail and annexes to handle the complexity. IIRC, the only thing te original C standard defined was that the number of bits had to conform to short <= int <= long with “int” being suggested to map to the native word size of the CPU. I think there are now a few more guarantees like long being at least 32bit and int being at least 16bit, but it is still a portability nightmare. Remember when it turned out that IP programming was extremely hard with Easy C because it took advantage of “short <= int” and mapped short to 32bit? An example for the “portability” nightmare and what you need to keep in mind is that what you wrote There is a lot of ground between the C way (let the CPU suggest what the compiler might implement with a bit of guidance by the standard) and the abstract way handling a “number” that I mentioned. Like e.g. requesting a numeric type like “must be able to handle values between a.b and x.y with a precision of p” and let the compiler map that onto whatever the CPU is capable of.
How inefficient to store a value between 0 and 5 in a whole int! |
Rick Murray (539) 13851 posts |
What you actually said was “decimal (fixed point) and floating point numbers”. While you mention “fixed point”, I decided to interpret “decimal” as integer because:
I didn’t say C was perfect. It’s better than BASIC (integers are always signed) and way better than anything using variant typing.
I wouldn’t count on C being particularly portable without an underlying ecology such as POSIX. Consider, for example, something simple like listing the contents of a directory. No part of standard C can do it. The library has to jump through hoops to support something like ungetc(), but you can’t list a directory. Or even have any way of parsing a filename.
Uh, no. Never used EasyC.
<facepalm> Okay, it is in the spec, but that’s LazyC more than EasyC! I mean, what’s the point of having different types if short=int=long?
Oh? Section 5.2.4.2.1 (yikes!) specifies that a char is 8 bits (defined as CHAR_BIT) with the ranges -127 to +127 for signed, and 0 to 255 for unsigned. There’s some complicated reason to do with complement why it isn’t supposed to be -128, though GCC and Norcroft define it as such in limits.h. Maybe it’s a more recent thing? Thus, a char is an eight bit byte… except maybe on weird old computers that don’t use eight bit bytes. ;-) That said, a string is an array of
How many languages actually give you that degree of control? And if (any?) did, wouldn’t this lead to the possibility of all sorts of weird bugs as the implication is that a request for a numeric type could have all sorts of differing values?
Depends on whether you define efficient as amount of memory consumed, or as amount of processing to get/set this value. An an ARM processor, using a 32 bit integer means it’s a clean and simple LDR/STR operation to handle the value. |
GavinWraith (26) 1563 posts |
A big programming project needs a team of programmers. What happens if Anders uses short floats for parametrizing widgets and Bob uses doubles, and each has their reasons? If you know how to deal with such clashes then there are good chances that you have read SICPE (Structure and Interpretation of Computer Programs by Abelson and Sussman) and you know how to deal with multiple representations of abstract data by using abstract datatypes. In the parlance of C you take a union type, with a tag that labels the format. |
Rick Murray (539) 13851 posts |
Plus the representation can be quirky (default @% is “g10.9”):
Umm… ;-) |
Pages: 1 2