awlite

POSIX AWK port of Text Elite game
git clone git://git.luxferre.top/awlite.git
Log | Files | Refs | README

commit dfc78807ab5d24903fed47f89b27de005ae4b132
parent d050177507dfdd7b83a5f7e7783867328969ea37
Author: Luxferre <lux@ferre>
Date:   Mon, 22 Jan 2024 21:39:01 +0200

Version 1.6: less bitwise op deps, save/load functionality, no cheatmode anymore

Diffstat:
MREADME | 31+++++++++++++++----------------
Mawlite.awk | 87++++++++++++++++++++++++++++++++++++++-----------------------------------------
2 files changed, 57 insertions(+), 61 deletions(-)

diff --git a/README b/README @@ -9,7 +9,7 @@ numerous fixes, optimizations and further gameplay improvements. The overall command for running awlite looks like this: -LC_ALL=C awk -f awlite.awk [-v NO_ALIEN_ITEMS=1] [-v CENSORED=1] [-v CHEAT=1] +LC_ALL=C awk -f awlite.awk [-v NO_ALIEN_ITEMS=1] [-v CENSORED=1] You can replace "awk" with "nawk", "busybox awk", "gawk --posix", "mawk -W posix" etc depending on which AWK implementation you have. @@ -20,8 +20,7 @@ nawk and busybox awk might not need it. Optionally, you can also supply these flags to change some game aspects: * -v NO_ALIEN_ITEMS=1 forces "Alien Items" goods unavailability in the game; -* -v CENSORED=1 replaces "Slaves", "Narcotics" and "Liquors" goods names; -* -v CHEAT=1 enables "cash" and "sneak" commands in the REPL. +* -v CENSORED=1 replaces "Slaves", "Narcotics" and "Liquors" goods names. Of course, awlite is fully scriptable, e.g. you can append < script.txt to the basic game launch command. @@ -43,16 +42,13 @@ From now on, the following commands are available (case-insensitive): * mkt: show local planetary system market prices * local: list planetary systems within 7 lightyears (your max fuel capacity) * hold: expand your cargo bay to 35t for 400 credits (one-time upgrade only) +* save (name): save the gamestate in the current working directory +* load (name): load the gamestate from the current working directory * help: display an in-game command help screen * rand: toggle between the AWK's native PRNG (default) and a custom one * quit: quit the game -The following commands are only available in the cheat mode (-v CHEAT=1): - -* cash (number): add (number) to your cash balance -* sneak (planetname): fly to planetname without spending fuel - -All commands except "hold", "cash" and "sneak" can be abbreviated by their +All commands except "hold", "save" and "load" can be abbreviated by their first letter. In addition, trade goods names can be abbreviated too (by several first letters). E.g. "b fo 5" is the same as "buy Food 5", and "q" is "quit". @@ -60,11 +56,10 @@ Fuel price is fixed at 0.2 CR/LY, you can hold 7LY of fuel at most. == Gameplay differences from the original TE 1.5 C version == -As of the current version, 1.5.8: +As of the current version, 1.6: * multiple typos corrected in text strings -* the "cash" and "sneak" commands are only available to the REPL if running - with -v CHEAT=1 +* the "cash" and "sneak" commands were removed since v1.6 * galaxy jumps are no longer free and cost 5000 credits each (like in classic Elite and Oolite) * cargo hold expansion also is non-free (400 credits) and can only be @@ -76,6 +71,7 @@ As of the current version, 1.5.8: * the following goods have been renamed: "Robot Slaves" to "Robots", "Liquor/Wines" to "Liquors", "Gem-Strones" to "Gem-stones" * market and local info tables are better aligned +* state saving/loading functionality introduced with "save"/"load" commands To be continued. This list is expected to grow in the future. @@ -129,11 +125,14 @@ Because the current AWK gaming scene is rather poor (besides a handful of some GAWK-specific games), and it is an interesting challenge to port such a title to an environment requiring nothing except a bare kernel and BusyBox to play. -- Why did you keep the cheating commands present in the original? +- Why didn't you keep the cheating commands present in the original? -To preserve backward compatibilty with some trading scripts written for the -original Text Elite versions. Once it is proven the scripts won't work -correctly anyway, the cheat mode will be removed from awlite. +In version 1.5.8, the commands "sneak" and "cash" were there in a special +"cheat mode" to preserve backward compatibilty with some trading scripts +written for the original Text Elite versions. Once it was proven the scripts +won't work correctly anyway, the cheat mode was removed starting with awlite +1.6. You can manipulate the savefiles to achieve the same functionality if +you really need to cheat. - Why don't the scripts give the same results as for the original TE.EXE? diff --git a/awlite.awk b/awlite.awk @@ -1,5 +1,5 @@ # awlite: POSIX AWK port of Text Elite -# Version 1.5.8 +# Version 1.6.0 # Original high-level algorithms from Text Elite 1.5 by Ian Bell, 1999, 2015 # Porting, corrections, improvements and optimizations by Luxferre, 2024 # @@ -9,7 +9,6 @@ # # Gameplay differences from the original C version of TE 1.5: # - multiple typos corrected in text strings -# - the "cash" and "sneak" commands are only available to the REPL if running with -v CHEAT=1 # - galaxy jumps are no longer free and cost 5000 credits each (like in classic Elite and Oolite) # - cargo hold expansion also is non-free (400 credits) and can only be done once from 20t to 35t (like in classic Elite) # - alien items are available by default, can be overridden with -v NO_ALIEN_ITEMS=1 @@ -17,6 +16,8 @@ # - the "politically correct" goods names are turned on with -v CENSORED=1 # - the following goods have been renamed: "Robot Slaves" to "Robots", "Liquor/Wines" to "Liquors", "Gem-Strones" to "Gem-stones" # - market and local info tables are better aligned +# - the "cash" and "sneak" commands are removed since v1.6 (use saves to cheat) +# - state saving functionality since v1.6 with "save" and "load" commands # ... to be continued ... # utility functions @@ -75,26 +76,6 @@ function bw_and(a, b, v, r) { } return int(r) } -function bw_or(a, b, v, r) { - v = 1; r = 0 - while(a > 0 || b > 0) { - if((a%2) == 1 || (b%2) == 1) r += v - a = int(a/2) - b = int(b/2) - v *= 2 - } - return int(r) -} -function bw_xor(a, b, v, r) { - v = 1; r = 0 - while(a > 0 || b > 0) { - if((a%2) != (b%2)) r += v - a = int(a/2) - b = int(b/2) - v *= 2 - } - return int(r) -} # ============================ # # Game code itself starts here # @@ -156,8 +137,9 @@ function makesystem(seeds, sinfo, p1, p2, p3, p4, lnf, ecof, sname) { sinfo["y"] = int(seeds[0] / 256) sinfo["govtype"] = int(seeds[1] / 8) % 8 sinfo["economy"] = int(seeds[0] / 256) % 8 - if(sinfo["govtype"] <= 1) sinfo["economy"] = bw_or(sinfo["economy"], 2) - ecof = bw_xor(sinfo["economy"], 7) + if(sinfo["govtype"] <= 1) + sinfo["economy"] = 2 + (sinfo["economy"]%2) + (sinfo["economy"]>3?4:0) + ecof = 7 - sinfo["economy"] sinfo["techlev"] = (sinfo["x"] % 4) + ecof + int(sinfo["govtype"] / 2) if((sinfo["govtype"] % 2) == 1) sinfo["techlev"]++ sinfo["population"] = 4 * (sinfo["techlev"]) + sinfo["economy"] + sinfo["govtype"] + 1 @@ -378,15 +360,6 @@ function dojump(s, dest, d, p, si) { return 1 } -# dojump without fuel expense -function dosneak(s, kp, r) { - kp = player["fuel"] - player["fuel"] = 666 - r = dojump(s) - player["fuel"] = kp - return r -} - # jump to next galaxy (planet number is preserved) function dogalhyp() { if(player["cash"] > game["galhypcost"]) { @@ -486,12 +459,6 @@ function dofuel(f) { return 1 } -# (cheat) alter cash command implementation -function docash(s) { - player["cash"] += int(10 * s) - if(player["cash"] < 0) player["cash"] = 0 -} - # show stock market function domkt() { displaymarket() @@ -505,17 +472,47 @@ function dohelp() { printf("\nSell product amount") printf("\nFuel amount (buy amount LY of fuel)") printf("\nJump planetname (limited by fuel)") - if(CHEAT) printf("\nSneak planetname (any distance - no fuel cost)") printf("\nGalhyp (jumps to next galaxy)") printf("\nInfo planetname (prints info on system)") printf("\nMkt (shows market prices)") printf("\nLocal (lists systems within 7 lightyears)") - if(CHEAT) printf("\nCash number (alters cash)") printf("\nHold (expand cargo bay to %dt)", game["cargoexpsize"]) + printf("\nSave playername (save game into current working directory)") + printf("\nLoad playername (load game from current working directory)") printf("\nQuit or ^D (exit)") printf("\nHelp (display this text)") printf("\nRand (toggle RNG)") - printf("\n\nAbbreviations allowed eg. b fo 5 = Buy Food 5, m= Mkt") + printf("\n\nAbbreviations allowed eg. b fo 5 = Buy Food 5, m = Mkt") +} + +# Save/load functionality + +function dosave(savename, fs, fn) { + gsub(/[^[:alnum:]]/, "_", savename) # sanitize all non-alnum chars + player["cargo"] = assocser(shipshold, "@") + fs = assocser(player, "|") + delete player["cargo"] + fn = savename ".awlite" + printf("%s\n", fs) >> fn # write the savefile + close(fn) + printf("\nGame saved in %s", fn) +} + +function doload(savename, fn, fs) { + gsub(/[^[:alnum:]]/, "_", savename) # sanitize all non-alnum chars + fn = savename ".awlite" + if((getline fs < fn) > 0) { # read the savefile + split("", player) # clear the player array + split("", shipshold) # clear the shipshold array + assocdes(fs, player, "|") + assocdes(player["cargo"], shipshold, "@") + delete player["cargo"] + split("", globalseeds) # init galaxy seeds + buildgalaxy(player["galaxynum"], globalseeds) # build the current galaxy + genmarket(0, economies[player["currentplanet"]]) # build local market + printf("\nGame loaded from %s", fn) + } else printf("\nError reading the savefile!") + close(fn) } # Game init procedure: first thing to call in the BEGIN block @@ -614,7 +611,7 @@ BEGIN { split("", globalseeds) # init galaxy seeds buildgalaxy(player["galaxynum"], globalseeds) # build the current galaxy genmarket(0, economies[player["currentplanet"]]) # build local market - printf("\nWelcome to awlite 1.5.8 (based on Text Elite 1.5)\n") + printf("\nWelcome to awlite 1.6.0\n") dohelp() # start the REPL printf("\n\nCash: %.1f> ", player["cash"]/10) @@ -635,8 +632,8 @@ BEGIN { else if(action == "j" || action == "jump") dojump(paramstr) else if(action == "f" || action == "fuel") dofuel(paramstr) else if(action == "hold") dohold(game["cargoexpsize"]) - else if(CHEAT && action == "cash") docash(paramstr) - else if(CHEAT && action == "sneak") dosneak(paramstr) + else if(action == "save") dosave(paramstr) + else if(action == "load") doload(paramstr) else printf("Unknown command") printf("\n\nCash: %.1f> ", player["cash"]/10) }