Web
Analytics
Log In  

5

Cart [#56397#] | Copy | Code | 2018-09-08 | Link
5

This is my little homage to the old-school 8-bit Ultima games as they were found on the C128. I hope you enjoy it.

It exhausts almost every resource available to a PICO-8 app, and required minimization before it could be converted into a cartridge. The full source of Minima is available on GitHub for anyone interested in how it works. I have also provided a manual for it in a couple of formats, so you may want to grab and peruse the Minima manual as a PDF or the Minima manual as an ePub as well as the cartridge itself.

If you have any comments, questions, or even just random thoughts related to it, I'll be happy to listen.

Please note version 1.0.1 fixes the getting stuck in the command reference when reselecting the command reference bug that was reported. Version 1.0.2 addresses the two remaining bugs that have been reported -- being unable to re-enter the upper levels, and loading a saved game sometimes messing up location.

minima ultima
P#56273 2018-09-06 12:46 ( Edited 2018-09-09 01:36)

::

Very deep, and rich, rewarding game. Marking as Favorite and gold star !

Nicely done, Feneric !

P#56275 2018-09-06 13:09 ( Edited 2018-09-06 13:11)

::

This looks nice.

Am I going to be asking "name? job?" a lot then?

P#56277 2018-09-06 13:26

::

@dw817 Thanks!

@enargy No, the interface doesn't really support it. There are only a handful of addressable keys out-of-the-box and so I had to get creative to make the commands fit in. As with all the Ultimas some people do provide clues as to how to win, but the dialog is somewhere between what III and IV offers. Each person has a couple of things to say, but there's no prompting them beyond the base dialog command.

P#56280 2018-09-06 13:41

::

Now Feneric, I don't know if you knew but current PICO-8 can read any alphanumeric key on the keyboard. You are not limited to the default PICO-8 buttons anymore.

I recently wrote a program to demonstrate this.

https://www.lexaloffle.com/bbs/?tid=31598

P#56290 2018-09-06 14:42

::

I actually had seen your example after I was quite a ways in, but at that point I didn't have the tokens to spare to change up the input method. Is that technique supported on the PocketCHIP, too?

I'd definitely use that approach for future projects.

P#56294 2018-09-06 14:53

::

I - don't have a PocketCHIP. That keyboard just looked ghastly. :)

Let me check what I wrote and see if I can optimize it.

It's a lot of unnecessary fluff. I think I can break it down:

cls()
poke(24365,1)
repeat
  k=stat(31)
  if (k>"") print(k)
  flip()
until k=="q"

Works here. Hit letters A-Z or digits 0-9, press "Q" to exit.

Make the key reading code (k=stat(31)) as part of your _UPDATE(), leave out the FLIP() and it should work just fine for reading the keyboard.

P#56296 2018-09-06 15:10

::

Even with that I don't think I can fit it without doing some major surgery. To give you an idea of where Minima is at relative to PICO-8 limitations, it's presently using 8189/8192 tokens, all the map space, all the sprites that don't overlap with the map space, 61/64 SFX slots, and (before minification) 55314 out of 65536 characters and 19331 out of 15360 compressed bytes (which is why the minification is presently required). I'd also at one point blown past the runtime memory allotment when I tried to save some tokens by making some table allocations less smart. I don't know how close I am to that runtime memory limit now, but I suspect not too far away...

If I'd known about that technique back when I first started I would have definitely tried to use it though. It would have made quite a few decisions a lot easier. Note the care with which I named spells and weapons, for example.

P#56302 2018-09-06 15:26

::

Wow - okay then. Hmm, I hadn't checked the size of your cart. You know in the future I was planning - still planning on writing an RPG Maker.

But yeah, I was wondering how you managed to cram in all that great conversation text from the sprites in the game. I see now it was a huge cost. Hmm ...

I'm looking at these lines in your code now:

o=n[1]
p=n[2]
q=n[3]
r=n[4]
s=n[5]
t=n[6]
u=n[7]
v=n[8]
w=n[9]
x=n[10]
y=n[11]
z=n[12]
ba=n[13]
bb=n[14]
bc=n[15]
bd=n[16]
be=n[17]
bf=n[18]
bg=n[19]
bh=n[20]
bi=n[21]
bj=n[22]

There may be a way to make that a bit smaller.

In any case, you'll be ready for next project with this keyboard input then, Feneric. :)

P#56305 2018-09-06 15:54 ( Edited 2018-09-06 15:59)

::

Token Police speaking: you are nowhere close to pico limits :) I can easily free around 1500 tokens but plugin in my usual json parser...
EDIT: you are already using standard lua optimizations :/

EDIT: early json version here: https://www.dropbox.com/s/uolo5sxopvgrzng/minima_json.p8?dl=0

Note: one of the main data structure should be slightly rewritten to be 'json' compatible. That woudl put the token count around 6400 (not to mention various simplifications that it would allow)

Couple of things to maximise json usage:

  • the json parser can reference anthing that is declared in the _g table. Ex:
_g.id=1
_g.update_player=function(self)
  self.x+=1
  self.y+=0.5
end
local player=json_parse('{"x":0,"y":0,"side":"id","update":"update_player"}')
-- prints 1
print(player.side)
-- calls update_player function
player:update()
  • json objects can be named. No need for:
creature=basetypes[1]
ankhtype=basetypes[2]
...

Simply:

basetypes=json_parse'{"creature":{"hp":10,"armor"...
  • clone your actual actors from json structure. I use the following function to create actors with random attributes:
function clone(src,dst)
    -- safety checks
    if(src==dst) assert()
    if(type(src)!="table") assert()
    dst=dst or {}
    for k,v in pairs(src) do
        if(not dst[k]) dst[k]=v
    end
    -- randomize selected values
    if src.rnd then
        for k,v in pairs(src.rnd) do
            -- don't overwrite existing values
            if not dst[k] then
                dst[k]=v[3] and rndarray(v) or rndlerp(v[1],v[2])
            end
        end
    end
    return dst
end
-- example use:
local player_template=json_parse('{"x":0,"y":0,"rnd":{"stamina":[1,8]}}')
local player=clone(player_template)
-- stamina is a random value between 1-8
print(player.stamina)

And cool game premises btw!

P#56310 2018-09-06 16:22 ( Edited 2018-09-07 16:07)

::

I'd be happy for you to take a stab at it, as there were features I had to drop in order to shoehorn in what I got in.

I think you need to look at the source prior to minification, though, via the link above. It's making pretty heavy use of metatables in order to spare repeated initialization, and it is using multi-variable initialization, no-parentheses calls, etc. everywhere in the original version. Apparently some of that is getting undone as part of the minification process. If you modify the minimized one we'll end up with something that'll be really gnarly to work on going down the road, but if you can reduce the token count of the clean version we ought to be able to do quite a bit with it. It's largely data-driven so it won't be a huge task to replace the maps and town data with a new set and thus create a new game if we preserve its data structure.

P#56314 2018-09-06 16:35

::

@freds72 -

> but plugin

Paging Dr. Freud! ;) :D

P#56315 2018-09-06 16:52

::

English is not my native language, things just don't click like that, you pervert =:)

P#56317 2018-09-06 17:07

::

As soon as I opened it up I'm like, "the music is nostalgic but the arrangement is grating," so rather than complain about it I just went in and reworked the whole thing. I didn't put in the triplet parts from the original(they're possible, just tedious since you have to run those patterns at higher speed) but everything's been given some more ornaments now.

__sfx__
000100002365024650206501e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00010000245202a6403075034660367703667034770326602f6602d75029650297502a640296402b7402c6502e6502f7502f6502d640296302563022720000000000000000000000000000000000000000000000
0001000017070160601505016050170501a06021060290702f0700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00020000276432f4732f4732f4732f4732f4732f4733b1733b2733b2733b2733b2733b2733b2733b2733b2733b2733b2333851500000000000000000000000000000000000000000000000000000000000000000
0002000002643024730347305473074730a4730d47311173162731b2731f27324273292732d27331273362733b2733e2333f51500000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
012000000742407422074220742502424024220242202425074240742207422074250242402422024220242507424074220742207425024240242202422024250742407422074220742502424024220242202425
0120000007424074220742207425024240242202422024250742407422074220742502424024220e4240e42207424074220e4240e42202424024220e4240e42207424074220e4240e42202424024220e4240e422
0120000007420074200e4200e42002420024200e4200e42007420074200e4200e4200242002420024200242007420074200e4200e42002420024200e4200e42007420074200e4200e42002420024200e4200e420
0120000007420074200e4200e42002420024200e4200e42007420074200e4200e4200242002420024200242007420074200742007420024200242002420024200742007420074200742002420024200242002420
0120000007420074200742007420024200242002420024200742007420074200742002420024200242002420074200742007420074200242002420024200242007420094200a4200c4200e4200e4200e4200e420
012000000c4200c4200c4200c420054200542005420054200a4200c4200e4200f42011420114201242012420134201342013420134200c4200c4200c4200c4200e4200a420094200742009420074200942007420
0120000007420074200e4200e42002420024200e4200e42007420074200e4200e42002420024200e4200e42007420074200e4200e42002420024200e4200e42007420074200e4200e42002420024200242002420
01200000004200042005420054200a4200a4200b4200b4200c4200e42010420124201342013420114201142014420144201442014420154201442012420104201242012420124201242014420144201a4201a420
01200000194201542010420154200d4200d4200d4200d420184201542010420154200c4200c4200c4200c42017420134200e420134200b4200b4200b4200b42016420134200e420134200a4200a4200c4200c420
01200000004200042005420054200a4200a4200b4200b4200c4200e42010420124201342013420124201242014420144201442014420154201442012420104201242012420124201242014420144201a4201a420
01200000134201342007420074200e4200e4200242002420074200742007420004000040000400004000040000400004000040000400004000040000400004000040000400004000040000400004000040000400
01200000004000040000400004000040000400004000040000400004000040000400004000040000400264252b4252d4252e4252b4252d4252e425304252d4252e4222e4253242232425304252e4252d42530425
012000002e4252d4252b4252e4252d4222d4252a4222a4252b4222b4252642226425244002440026422264252b2242d2242e2242b2242d2242e224302242d2242e2242e2223222432222302242e2242d22430224
012000002e2242d2242b2242e2242d2242d2222a2242a2222b2242b2222622426222244002440026422264252b4252d4252e4222e4252d4252e42530422304252e425304253242232425304252e4252d4222d425
012000002e4252d4252b4222b4252d4252b4252a4222a4252b4252d4252b4222b425264222642226422264252b4252d4252e4252b4252d4252e425304252d4252e4222e4253242232425304252e4252d42530425
012000002e4252d4252b4252e4252d4222d4252a4222a4252b4222b4252642226425244002440026224262222d2242b2242d2242b2242a2242a222332243322232224322222e2242e2222e2222a4002e2242e222
01200000302242e224302242e2242d2242d222332243322232224322222e2242e2222e2222e2222d2242d2222e2242e2222b2242b222292242922227224272222622426222262222622229224292222922229222
012000002b2242d2242e2242b2242d2242e224302242d2242e2242e2223222432222302242e2242d224302242e2242d2242b2242e2242d2242d2222a2242a2222b2242b222262242622200000000002642226425
012000002b4252d4252e4222e4252d4252e42530422304252e425304253242232425304252e4252d4222d4252e4252d4252b4222b4252d4252b4252a4222a4252b4252d4252b4222b42526422264222642226425
012000002742526425244222442526422264222642226425284252642524422244252642226425274222742528422284252f4222f425314252f4252d4252c4252d4222d4222d4222d4252f4222f4252c4222c425
012000002d425284252542528425214222142221422214252d425284252442528425214222142221422214252b4252642523425264251f4221f4221f4221f4252b4252642522425264251f4221f4251e4221e425
012000002742526425244222442526422264222642226425284252642524422244252642226425274222742528422284252f4222f425314252f4252d4252c4252d4222d4222d4222d4252f4222f4252c4222c425
012000002b4252d4252e425304253242533425364253242537422374223742237412374152100022000210001f0001f000210001f0001e0001e00000000000000000000000000000000000000000000000000000
01200000220051a0051f005220051a0051f005210051e005000000000000000000000000000000000000000022734267342b73422734267342b7342d7342a7342b7342b7322e7342e7322d7342b7342a7342d734
012000002b7342b73226734267322a7342a73224734247322273426734217341f7341a7341b7341e734247342a734287342a73428734267342673230734307322e7342e7322b7342b7342b7322b7002b7342b732
012000002d7342b7342d7342b734297342973230734307322e7342e7322973429732297322973226734267322b7342b7322773427732217342173224734247322273422732227322273221734217322173221732
0120000022734267342b7342e734267342b7342d7342a7342b7342b7322e7342e7322d7342b7342a7342d7342b7342b73226734267322a7342a7322473424732227341a734227341f7341a7341b7341e73424734
012000002473422734217342173222734227321f7341f732247342373421734217342373423732237342373223734237322373223732287342873228732284002873428732277342773228734287322873228732
01200000287342573421734257341c7341c7321c7321c732287342473421734247341c7341c7321c7321c73226734237341f734237341a7341a7321a7321a73226732227341f734227341a7341a7321a7341a732
0120000022734217341f73422734217341f7341e734217341f7341f7321f7321f7221f71500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
011800000924409225102441022515244152251024410225112441122011210112150020000200002000020009244092251024410225152441522518244182251c2441c2201c2101c21500200002000020000000
011800000924409225102441022515244152251024410225112441122011210112150020000200002000020010244102251124411225102440e2440c2440b2440924409220092100921500200002000020000000
01180000005001a7241a72521722217252672426725217222172522722227222272500700007000070000700007001a7241a725217222172526724267251d722297252d7222d7222d72500700007000070000500
01180000007001a7241a725217222172526724267252172221725227222272222725007000070000700007000070021724217252272222725217241f7251d7221c7251a7221a7221a72500700007000070000700
01180000005000954009545105401054515540155451054010545115401154011545005001152500500115150050009540095451054010545155401554518540185451c5401c5401c545005001c525005001c515
01180000000000954009545105401054515540155451054010545115401154011545000001152500000115150000010540105451154011545105450e5450c5450b54509540095400954500000000000000000000
011800002471024720247302474024750247402473024720217402173021720217100070000700007000070024710247202473024740247502474024730247201f7401f7301f7201f7101c700007000070000700
011800002471024720247302474024750247402473024720217402173021720217100000000000000000000020710207202073020740237502374023730237202474024730247202471000000000000000000000
01180000247102472028730287402d7502d740287302872027740277302772027710007000070000700007002171024720287302c7402d7502b74028730287202b7402b7302b7202b71000700007000070000000
011800002471024720287302874024750247402873028720297402973029720297100070000700007000070028710267202873024740267502474026730237202174021730217202171000700007000070000700
0118000015710157201c7301c74021750217401c7301c7201d7401d7301d7201d7100070000700007000070021710217201c7301c740217502174024730247202874028730287202871000700007000070000000
0118000015720157201c7201c72021720217201c7201c7201d7201d7201d7201d720007000070000700007001c7201c7201d7201d7201c7201a72018720177201572015720157201572000000000000000000000
011800000000015120151201c1201c12021120211201c1201c1201d1201d1201d1201d1250000000000000000000015120151201c1201c1202112021120241202412028122281222812228125000000000000000
011800000010015120151201c1201c12021120211201c1201c1201d1201d1201d1201d125001000010000100001001c1201c1201d1201d1201c1201a120181201712015122151221512215125001000010000100
01180000007003572435725397223972532724327253972239725367223672236725367000070000700007000070032724357253b7223172532724317253b7223b72530722307223072530700007000070000700
011800000070035724357253972239725327243272539722397253672236722367253670000700007000070000700397243772539722357253772435725377223472532722327223272532700007000070000700
011800001800024421244202442024420244202442224412200002142021420204211800000000000000000021000244212442024420244202442024422244121800020421204222041200000000000000000000
011800001800024421244202442024420244202442224412000002142021420204210000000000000000000000000204202042220422234212342223422244212442024422244222442224412244122441500000
011800003451434512345123451234512345123451234515335103351033510335150000000000000000000034514345123451234512345123451234512345153451034510345103451500000000000000000000
011800003451434512345123451234512345123451234515355103551035510355150000000000000000000034514345103451034510385103851038510385103951039510395103951500000000000000000000
01180000345143451039510395103c5103b510395103951539510395123951239515000000000000000000003051434510395103b5103c5103b51039510395123b5103b5123b5123b51500000000000000000000
01180000345143451039510395103c5103b510395103951539510395123951239515000000000000000000003c5143b5103c510395103b510395103b510385103951039512395123951500000000000000000000
011800001c0101c02023010230202801028020230102302024010240202402024015000000000000000000001d0101d020230102302028010280202b0102b0202f0102f0202f0202f01500000000000000000000
011800001c0101c02023010230202801028020230102302024010240202402024015000000000000000000002301023020240102402023010210101f0101e0101c0101c0201c0201c01500000000000000000000
01180000000002d1102d11034110341103911039110341103411035110351103511035115000000000000000000002d1102d110341103411039110391103c1103c11034110341103411034115000000000000000
01180000001002d1102d1103411034110391103911034110341103511035110351103511500100001000010000100341103411035110351103411032110301102f1102d1102d1102d1102d115001000010000100
011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__music__
00 06114344
00 07124344
00 08134344
00 09141d44
00 0a151e44
00 0b161f44
00 0c172044
00 0c182044
00 0d192144
00 0e1a2244
00 06174344
00 0c172044
00 0d1b2144
00 0e1a2244
00 06182044
00 0c182044
02 101c2344
01 246a4344
00 25424344
00 242a3644
00 252b3744
00 242c3844
00 252d3944
00 242e3a44
00 252f3b44
00 24303c44
00 25313d44
00 26324344
00 27334344
00 28344344
02 29354344

Having finished my quest, I played the game start to finish. Lots of fun.

It feels like Ultimas I and II in terms of fleshing out the content - some grinding, a handful of puzzles, a lot of filler parts. Which is understandable since RPG content is pretty tough to fill in, especially so when you have PICO-8 limits to work against. In those games the dungeons were tacked on and just served to grind experience - and here it's the same apart from the final dungeon...bug report: when I won I tried to ascend to the dungeon again and it sent me to an empty void.

P#56359 2018-09-07 07:39

::

Thanks, I'm glad you like it.

Yeah, story-wise it's pretty similar in complexity to Ultima II, scale-wise it's closer to Ultima I, but it's got a few Ultima III & Ultima IV sorts of features thrown in, too. Space constraints were what limited me the most with regard to RPG content. I'd planned out more people with more custom dialog and one more puzzle thread that I just couldn't work in (along with a list of specific features that I'd had to drop at various points along the way -- if you're interested in the full list I included them on the GitHub page). One of the final things I had to give up was treasure chests in dungeons. These would have reduced grind and made the mimics a little more meaningful.

Even without chests there actually is something to find in each of the three non-final dungeons in Minima. Obviously none of them are essential. They can make winning easier though. There are a few clues in there about them, but they're terser than I'd like.

Thanks for the music; I'll definitely give it a listen.

P#56364 2018-09-07 09:03

::

Was just listening to the music edition you prepared, TripleFox. Pretty good !

P#56377 2018-09-07 15:36

::

@triplefox: Your take on the music is great, better than mine. Are you sure it's even possible to do the triplet parts from the original within the limits we've got? I'm not questioning whether or not the timing can be done, as obviously the answer there is "yes", but more whether or not it'd fit within the available count. When I'd considered it earlier I didn't think it could.

@freds72: Yeah, I was already using the standard optimizations plus a bunch of other things that I'm sure are very much non-standard. If you've got an efficient JSON parser for PICO-8 that could definitely save 1000 tokens easily while still keeping Minima data-driven (and thus easily usable as a framework for other similar types of games).

P#56420 2018-09-08 17:39

::

Iíve already edited my initial post with details and examples. The json version is actually even more data driven than the original!
The full json version should be around 6400 tokens (exercise left to the reader - the version I posted is working but not fully converted, some code & data must be modified to be fully json-compatible ;)

P#56433 2018-09-09 01:34

::

@Feneric: I haven't measured the pattern counts, but my suspicion is that it wouldn't impact as much as we think. The way PICO-8 music deals with short patterns is to loop them until the longest one ends, hence you have some room to modulate speed/size over the course of the song to only include the fast stuff where it's needed. For most triplet patterns this means going from 64 to 96 effective rows - or by multiplying the rows by three and running it three times as fast. Better hope your speed is divisible by three! As a last resort you could turn to the SFX instruments feature, and define SFX to play notes with triplet offsetting.

Given all those considerations it could easily turn into a juggling act where it could be done, or mostly done, but it's logistically difficult and the whole song has to run a little bit faster or slower, which is why I didn't look into it closely.

The other way that this could be done, which would take a lot of tokens to pull off, is to rewrite it in MML form. And then generate the pattern data on demand by compiling it. AFAIK we don't have any such compiler right now. It would be an interesting tech project.

P#56434 2018-09-09 01:36

Log in to post a comment

user:
password:

New User | Account Help
:: New User
X
About | Contact | Updates | Terms of Use
Follow Lexaloffle:        
Generated 2018-09-24 08:12 | 0.288s | 1835k | Q:35