prog8/examples/textelite.p8

991 lines
32 KiB
Plaintext
Raw Normal View History

2020-10-04 15:47:57 +00:00
%import textio
2020-10-09 23:29:10 +00:00
%import conv
2020-10-14 00:51:00 +00:00
%import diskio
%import string
2020-11-22 17:17:43 +00:00
%import test_stack
2020-10-09 23:46:19 +00:00
%option no_sysinit
%zeropage basicsafe
2020-10-09 23:29:10 +00:00
; Prog8 adaptation of the Text-Elite galaxy system trading simulation engine.
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
2020-10-11 19:59:38 +00:00
; Note: this program is compatible with C64 and CX16.
2021-01-20 00:36:46 +00:00
; TODO fix save (and load?) crash bug
2020-10-04 15:47:57 +00:00
main {
2020-10-10 14:21:51 +00:00
const ubyte numforLave = 7 ; Lave is 7th generated planet in galaxy one
const ubyte numforZaonce = 129
const ubyte numforDiso = 147
const ubyte numforRiedquat = 46
2020-10-04 15:47:57 +00:00
sub start() {
txt.lowercase()
2020-10-14 00:51:00 +00:00
txt.print("\u000c\n --- TextElite v1.1 ---\n")
2020-10-04 19:53:16 +00:00
2020-10-14 21:43:38 +00:00
galaxy.travel_to(1, numforLave)
2020-10-10 22:38:38 +00:00
market.init(0) ; Lave's market is seeded with 0
2020-10-11 17:26:20 +00:00
ship.init()
2020-10-10 14:21:51 +00:00
planet.display(false)
2020-10-09 22:15:38 +00:00
2020-10-09 23:29:10 +00:00
repeat {
2020-11-22 17:17:43 +00:00
; test_stack.test()
2020-10-09 23:29:10 +00:00
str input = "????????"
txt.print("\nCash: ")
util.print_10s(ship.cash)
2020-10-10 14:21:51 +00:00
txt.print("\nCommand (?=help): ")
ubyte num_chars = txt.input_chars(input)
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-10 14:21:51 +00:00
if num_chars {
when input[0] {
'?' -> {
2020-10-11 00:22:09 +00:00
txt.print("\nCommands are:\n"+
2020-10-11 19:38:25 +00:00
"buy jump info cash >=save\n"+
"sell teleport market hold <=load\n"+
"fuel galhyp local quit\n")
2020-10-10 14:21:51 +00:00
}
'q' -> break
'b' -> trader.do_buy()
's' -> trader.do_sell()
'f' -> trader.do_fuel()
'j' -> trader.do_jump()
't' -> trader.do_teleport()
'g' -> trader.do_next_galaxy()
'i' -> trader.do_info()
'm' -> trader.do_show_market()
'l' -> trader.do_local()
'c' -> trader.do_cash()
'h' -> trader.do_hold()
2020-10-11 19:38:25 +00:00
'<' -> trader.do_load()
'>' -> trader.do_save()
2020-10-10 14:21:51 +00:00
}
2020-10-09 23:29:10 +00:00
}
2020-10-10 14:21:51 +00:00
}
}
}
trader {
str Savegame = "↑commander.save"
2020-10-11 16:19:09 +00:00
str input = "??????????"
2020-10-10 14:21:51 +00:00
ubyte num_chars
2020-10-14 00:51:00 +00:00
struct SaveData {
2020-10-14 21:43:38 +00:00
ubyte galaxy
ubyte planet
ubyte cargo0
ubyte cargo1
ubyte cargo2
ubyte cargo3
ubyte cargo4
ubyte cargo5
ubyte cargo6
ubyte cargo7
ubyte cargo8
ubyte cargo9
ubyte cargo10
ubyte cargo11
ubyte cargo12
ubyte cargo13
ubyte cargo14
ubyte cargo15
ubyte cargo16
uword cash
ubyte max_cargo
ubyte fuel
2020-10-14 00:51:00 +00:00
}
SaveData savedata
2020-10-11 19:38:25 +00:00
sub do_load() {
2020-10-14 00:51:00 +00:00
txt.print("\nLoading universe...")
if diskio.load(8, Savegame, &savedata) {
txt.print("ok\n")
} else {
txt.print("\ni/o error: ")
2020-12-21 22:45:26 +00:00
txt.print(diskio.status(8))
2021-01-08 15:56:17 +00:00
txt.nl()
return
2020-10-14 00:51:00 +00:00
}
2020-10-14 21:43:38 +00:00
ship.cash = savedata.cash
ship.Max_cargo = savedata.max_cargo
ship.fuel = savedata.fuel
sys.memcopy(&savedata.cargo0, ship.cargohold, len(ship.cargohold))
2020-10-14 21:43:38 +00:00
galaxy.travel_to(savedata.galaxy, savedata.planet)
2020-10-14 00:51:00 +00:00
planet.display(false)
2020-10-11 19:38:25 +00:00
}
sub do_save() {
2020-10-14 21:43:38 +00:00
savedata.galaxy = galaxy.number
savedata.planet = planet.number
savedata.cash = ship.cash
savedata.max_cargo = ship.Max_cargo
savedata.fuel = ship.fuel
sys.memcopy(ship.cargohold, &savedata.cargo0, len(ship.cargohold))
2020-10-14 00:51:00 +00:00
txt.print("\nSaving universe...")
diskio.delete(8, Savegame)
if diskio.save(8, Savegame, &savedata, sizeof(savedata)) {
txt.print("ok\n")
} else {
txt.print("\ni/o error: ")
2020-12-21 22:45:26 +00:00
txt.print(diskio.status(8))
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-14 00:51:00 +00:00
}
2020-10-11 19:38:25 +00:00
}
2020-10-10 14:21:51 +00:00
sub do_jump() {
2020-10-11 16:19:09 +00:00
txt.print("\nJump to what system? ")
jump_to_system()
2020-10-10 14:21:51 +00:00
}
sub do_teleport() {
2020-10-11 16:19:09 +00:00
txt.print("\nCheat! Teleport to what system? ")
2020-10-11 19:38:25 +00:00
ubyte fuel = ship.fuel
ship.fuel = 255
2020-10-11 16:19:09 +00:00
jump_to_system()
ship.fuel = fuel
}
sub jump_to_system() {
void txt.input_chars(input)
2020-10-11 19:38:25 +00:00
ubyte current_planet = planet.number
ubyte x = planet.x
ubyte y = planet.y
if galaxy.search_closest_planet(input) {
ubyte distance = planet.distance(x, y)
if distance <= ship.fuel {
galaxy.init_market_for_planet()
ship.fuel -= distance
txt.print("\n\nHyperspace jump! Arrived at:\n")
planet.display(true)
return
}
txt.print("Insufficient fuel\n")
} else {
txt.print(" Not found!\n")
}
2020-10-14 21:43:38 +00:00
galaxy.travel_to(galaxy.number, current_planet)
2020-10-10 14:21:51 +00:00
}
sub do_buy() {
2020-10-11 16:36:20 +00:00
txt.print("\nBuy what commodity? ")
str commodity = "???????????????"
void txt.input_chars(commodity)
2020-10-11 17:26:20 +00:00
ubyte ci = market.match(commodity)
if ci & 128 {
txt.print("Unknown\n")
} else {
txt.print("\nHow much? ")
void txt.input_chars(input)
ubyte amount = conv.str2ubyte(input)
if market.current_quantity[ci] < amount {
txt.print(" Insufficient supply!\n")
} else {
uword price = market.current_price[ci] * amount
txt.print(" Total price: ")
util.print_10s(price)
if price > ship.cash {
txt.print(" Not enough cash!\n")
} else {
ship.cash -= price
ship.cargohold[ci] += amount
market.current_quantity[ci] -= amount
}
}
}
2020-10-10 14:21:51 +00:00
}
sub do_sell() {
2020-10-11 17:26:20 +00:00
txt.print("\nSell what commodity? ")
str commodity = "???????????????"
void txt.input_chars(commodity)
ubyte ci = market.match(commodity)
if ci & 128 {
txt.print("Unknown\n")
} else {
txt.print("\nHow much? ")
void txt.input_chars(input)
ubyte amount = conv.str2ubyte(input)
if ship.cargohold[ci] < amount {
txt.print(" Insufficient supply!\n")
} else {
uword price = market.current_price[ci] * amount
txt.print(" Total price: ")
util.print_10s(price)
ship.cash += price
ship.cargohold[ci] -= amount
market.current_quantity[ci] += amount
}
}
2020-10-10 14:21:51 +00:00
}
sub do_fuel() {
txt.print("\nBuy fuel. Amount? ")
void txt.input_chars(input)
2020-10-11 16:36:20 +00:00
ubyte buy_fuel = 10*conv.str2ubyte(input)
2020-10-11 16:19:09 +00:00
ubyte max_fuel = ship.Max_fuel - ship.fuel
if buy_fuel > max_fuel
buy_fuel = max_fuel
uword price = buy_fuel as uword * ship.Fuel_cost
if price > ship.cash {
txt.print("Not enough cash!\n")
} else {
ship.cash -= price
ship.fuel += buy_fuel
}
2020-10-10 14:21:51 +00:00
}
sub do_cash() {
txt.print("\nCheat! Set cash amount: ")
void txt.input_chars(input)
2020-10-10 22:38:38 +00:00
ship.cash = conv.str2uword(input)
2020-10-10 14:21:51 +00:00
}
sub do_hold() {
2020-10-11 16:19:09 +00:00
txt.print("\nCheat! Set cargohold size: ")
void txt.input_chars(input)
2020-10-11 16:36:20 +00:00
ship.Max_cargo = conv.str2ubyte(input)
2020-10-10 14:21:51 +00:00
}
sub do_next_galaxy() {
2020-10-14 21:43:38 +00:00
galaxy.travel_to(galaxy.number+1, planet.number)
2020-10-10 14:21:51 +00:00
planet.display(false)
}
sub do_info() {
txt.print("\nSystem name (empty=current): ")
num_chars = txt.input_chars(input)
if num_chars {
2020-10-11 19:38:25 +00:00
ubyte current_planet = planet.number
if galaxy.search_closest_planet(input) {
planet.display(false)
} else {
txt.print(" Not found!")
}
2020-10-14 21:43:38 +00:00
galaxy.travel_to(galaxy.number, current_planet)
2020-10-10 14:21:51 +00:00
} else {
2020-10-09 23:29:10 +00:00
planet.display(false)
2020-10-09 22:15:38 +00:00
}
2020-10-04 15:47:57 +00:00
}
2020-10-10 14:21:51 +00:00
sub do_local() {
galaxy.local_area()
2020-10-04 15:47:57 +00:00
}
2020-10-10 14:21:51 +00:00
sub do_show_market() {
2020-10-10 21:24:15 +00:00
market.display()
txt.print("\nFuel: ")
util.print_10s(ship.fuel)
2020-10-11 16:19:09 +00:00
txt.print(" Cargohold space: ")
txt.print_ub(ship.cargo_free())
2020-10-10 21:24:15 +00:00
txt.print("t\n")
2020-10-10 14:21:51 +00:00
}
}
ship {
2020-10-11 16:19:09 +00:00
const ubyte Max_fuel = 70
const ubyte Fuel_cost = 2
ubyte Max_cargo = 20
2020-10-10 14:21:51 +00:00
ubyte fuel = Max_fuel
2020-10-11 16:19:09 +00:00
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
2020-10-10 21:24:15 +00:00
ubyte[17] cargohold = 0
2020-10-11 17:26:20 +00:00
sub init() {
sys.memset(cargohold, len(cargohold), 0)
2020-10-11 17:26:20 +00:00
}
2020-10-11 16:19:09 +00:00
sub cargo_free() -> ubyte {
ubyte ci
ubyte total = 0
for ci in 0 to len(cargohold)-1 {
if market.units[ci]==0 ; tonnes only
total += cargohold[ci]
}
return Max_cargo - total
2020-10-10 21:24:15 +00:00
}
}
market {
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
2020-10-10 22:38:38 +00:00
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
2020-10-10 21:24:15 +00:00
ubyte[17] basequants = [$06, $0A, $02, $E2, $FB, $36, $08, $38, $28, $11, $1D, $DC, $35, $42, $37, $FA, $C0]
ubyte[17] maskbytes = [$01, $03, $07, $1F, $0F, $03, $78, $03, $07, $1F, $07, $3F, $03, $07, $1F, $0F, $07]
ubyte[17] units = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0]
str[17] names = ["Food", "Textiles", "Radioactives", "Slaves", "Liquor/Wines", "Luxuries", "Narcotics", "Computers",
"Machinery", "Alloys", "Firearms", "Furs", "Minerals", "Gold", "Platinum", "Gem-Stones", "Alien Items"]
ubyte[17] current_quantity = 0
2020-10-10 22:38:38 +00:00
uword[17] current_price = 0
sub init(ubyte fluct) {
; Prices and availabilities are influenced by the planet's economy type
; (0-7) and a random "fluctuation" byte that was kept within the saved
; commander position to keep the market prices constant over gamesaves.
; Availabilities must be saved with the game since the player alters them
; by buying (and selling(?))
;
; Almost all operations are one byte only and overflow "errors" are
; extremely frequent and exploited.
;
; Trade Item prices are held internally in a single byte=true value/4.
; The decimal point in prices is introduced only when printing them.
; Internally, all prices are integers.
; The player's cash is held in four bytes.
ubyte ci
for ci in 0 to len(names)-1 {
word product
byte changing
product = planet.economy as word * gradients[ci]
changing = fluct & maskbytes[ci] as byte
ubyte q = (basequants[ci] as word + changing - product) as ubyte
if q & $80
q = 0 ; clip to positive 8-bit
current_quantity[ci] = q & $3f
q = (baseprices[ci] + changing + product) as ubyte
current_price[ci] = q * $0004
}
current_quantity[16] = 0 ; force nonavailability of Alien Items
}
2020-10-10 21:24:15 +00:00
sub display() {
ubyte ci
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-11 16:19:09 +00:00
planet.print_name_uppercase()
txt.print(" trade market:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
2020-10-10 21:24:15 +00:00
for ci in 0 to len(names)-1 {
util.print_right(13, names[ci])
txt.print(" ")
2020-10-10 21:24:15 +00:00
util.print_10s(current_price[ci])
txt.print(" ")
txt.print_ub(current_quantity[ci])
when units[ci] {
0 -> txt.chrout('t')
1 -> txt.print("kg")
2 -> txt.chrout('g')
}
2020-10-10 21:24:15 +00:00
txt.print(" ")
txt.print_ub(ship.cargohold[ci])
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-10 21:24:15 +00:00
}
}
2020-10-11 17:26:20 +00:00
sub match(uword nameptr) -> ubyte {
ubyte ci
for ci in 0 to len(names)-1 {
if util.prefix_matches(nameptr, names[ci])
return ci
}
return 255
}
2020-10-04 15:47:57 +00:00
}
2020-10-09 20:25:12 +00:00
galaxy {
const uword GALSIZE = 256
const uword base0 = $5A4A ; seeds for the first galaxy
2020-10-09 20:25:12 +00:00
const uword base1 = $0248
const uword base2 = $B753
2020-10-10 14:21:51 +00:00
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
2020-10-09 20:25:12 +00:00
ubyte number
2020-10-10 14:21:51 +00:00
2020-10-09 20:25:12 +00:00
uword[3] seed
sub init(ubyte galaxynum) {
2020-10-10 14:21:51 +00:00
number = 1
2020-10-09 23:29:10 +00:00
planet.number = 255
2020-10-10 02:37:12 +00:00
seed = [base0, base1, base2]
2020-10-09 20:47:42 +00:00
repeat galaxynum-1 {
2020-10-09 20:25:12 +00:00
nextgalaxy()
}
}
sub nextgalaxy() {
2020-10-10 02:37:12 +00:00
seed = [twist(seed[0]), twist(seed[1]), twist(seed[2])]
2020-10-10 14:21:51 +00:00
number++
if number==9
number = 1
}
2020-10-14 21:43:38 +00:00
sub travel_to(ubyte galaxynum, ubyte system) {
init(galaxynum)
2020-10-10 14:21:51 +00:00
generate_next_planet() ; always at least planet 0 (separate to avoid repeat ubyte overflow)
repeat system {
generate_next_planet()
}
planet.name = make_current_planet_name()
2020-10-11 19:38:25 +00:00
init_market_for_planet()
}
sub init_market_for_planet() {
2020-10-10 22:38:38 +00:00
market.init(lsb(seed[0])+msb(seed[2]))
2020-10-09 20:25:12 +00:00
}
2020-10-11 19:38:25 +00:00
sub search_closest_planet(uword nameptr) -> ubyte {
ubyte x = planet.x
ubyte y = planet.y
ubyte current_planet_num = planet.number
init(number)
ubyte found = false
ubyte current_closest_pi
ubyte current_distance = 127
ubyte pi
for pi in 0 to 255 {
generate_next_planet()
planet.name = make_current_planet_name()
if util.prefix_matches(nameptr, planet.name) {
ubyte distance = planet.distance(x, y)
if distance < current_distance {
current_distance = distance
current_closest_pi = pi
found = true
}
}
}
if found
2020-10-14 21:43:38 +00:00
travel_to(number, current_closest_pi)
2020-10-11 19:38:25 +00:00
else
2020-10-14 21:43:38 +00:00
travel_to(number, current_planet_num)
2020-10-11 19:38:25 +00:00
return found
}
2020-10-10 14:21:51 +00:00
sub local_area() {
ubyte current_planet = planet.number
ubyte px = planet.x
ubyte py = planet.y
ubyte pn = 0
init(number)
txt.print("\nGalaxy #")
txt.print_ub(number)
txt.print(" - systems in vicinity:\n")
do {
generate_next_planet()
ubyte distance = planet.distance(px, py)
if distance <= ship.Max_fuel {
if distance <= ship.fuel
txt.chrout('*')
else
txt.chrout('-')
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-10 14:21:51 +00:00
planet.name = make_current_planet_name()
planet.display(true)
txt.print(" (")
util.print_10s(distance)
txt.print(" LY)\n")
}
pn++
} until pn==0
2020-10-14 21:43:38 +00:00
travel_to(number, current_planet)
2020-10-10 14:21:51 +00:00
}
ubyte pn_pair1
ubyte pn_pair2
ubyte pn_pair3
ubyte pn_pair4
ubyte longname
2020-10-09 22:15:38 +00:00
sub generate_next_planet() {
determine_planet_properties()
2020-10-10 14:21:51 +00:00
longname = lsb(seed[0]) & 64
2020-10-09 22:15:38 +00:00
; Always four iterations of random number
2020-10-10 14:21:51 +00:00
pn_pair1 = (msb(seed[2]) & 31) * 2
2020-10-09 22:15:38 +00:00
tweakseed()
2020-10-10 14:21:51 +00:00
pn_pair2 = (msb(seed[2]) & 31) * 2
2020-10-09 22:15:38 +00:00
tweakseed()
2020-10-10 14:21:51 +00:00
pn_pair3 = (msb(seed[2]) & 31) * 2
2020-10-09 22:15:38 +00:00
tweakseed()
2020-10-10 14:21:51 +00:00
pn_pair4 = (msb(seed[2]) & 31) * 2
2020-10-09 22:15:38 +00:00
tweakseed()
2020-10-10 14:21:51 +00:00
}
2020-10-09 20:25:12 +00:00
2020-10-10 14:21:51 +00:00
sub make_current_planet_name() -> str {
2020-10-09 20:47:42 +00:00
ubyte ni = 0
2020-10-10 14:21:51 +00:00
str name = " " ; max 8
2020-10-10 14:21:51 +00:00
if pn_pairs[pn_pair1] != '.' {
name[ni] = pn_pairs[pn_pair1]
2020-10-09 20:47:42 +00:00
ni++
}
if pn_pairs[pn_pair1+1] != '.' {
name[ni] = pn_pairs[pn_pair1+1]
2020-10-09 20:47:42 +00:00
ni++
}
2020-10-10 14:21:51 +00:00
if pn_pairs[pn_pair2] != '.' {
name[ni] = pn_pairs[pn_pair2]
2020-10-09 20:47:42 +00:00
ni++
}
if pn_pairs[pn_pair2+1] != '.' {
name[ni] = pn_pairs[pn_pair2+1]
2020-10-09 20:47:42 +00:00
ni++
}
2020-10-10 14:21:51 +00:00
if pn_pairs[pn_pair3] != '.' {
name[ni] = pn_pairs[pn_pair3]
2020-10-09 20:47:42 +00:00
ni++
}
if pn_pairs[pn_pair3+1] != '.' {
name[ni] = pn_pairs[pn_pair3+1]
2020-10-09 20:47:42 +00:00
ni++
}
2020-10-09 22:15:38 +00:00
if longname {
2020-10-10 14:21:51 +00:00
if pn_pairs[pn_pair4] != '.' {
name[ni] = pn_pairs[pn_pair4]
2020-10-09 20:47:42 +00:00
ni++
}
if pn_pairs[pn_pair4+1] != '.' {
name[ni] = pn_pairs[pn_pair4+1]
2020-10-09 20:47:42 +00:00
ni++
}
}
2020-10-10 14:21:51 +00:00
name[ni] = 0
return name
2020-10-09 20:25:12 +00:00
}
2020-10-09 22:15:38 +00:00
sub determine_planet_properties() {
; create the planet's characteristics
2020-10-09 23:29:10 +00:00
planet.number++
2020-10-09 22:15:38 +00:00
planet.x = msb(seed[1])
planet.y = msb(seed[0])
planet.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
planet.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
if planet.govtype <= 1
planet.economy = (planet.economy | 2)
planet.techlevel = (msb(seed[1]) & 3) + (planet.economy ^ 7)
planet.techlevel += planet.govtype >> 1
if planet.govtype & 1
planet.techlevel++
planet.population = 4 * planet.techlevel + planet.economy
planet.population += planet.govtype + 1
planet.productivity = ((planet.economy ^ 7) + 3) * (planet.govtype + 4)
planet.productivity *= planet.population * 8
ubyte seed2_msb = msb(seed[2])
planet.radius = mkword((seed2_msb & 15) + 11, planet.x)
planet.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
if planet.species_is_alien {
planet.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
planet.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
planet.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
planet.species_kind = (planet.species_look + (seed2_msb & 3)) & 7 ;Add bits 0-1 of w2_hi to A from previous step, and take bits 0-2 of the result
}
2020-10-10 02:37:12 +00:00
planet.goatsoup_seed = [lsb(seed[1]), msb(seed[1]), lsb(seed[2]), seed2_msb]
2020-10-09 22:15:38 +00:00
}
2020-10-09 20:25:12 +00:00
sub tweakseed() {
uword temp = seed[0] + seed[1] + seed[2]
seed[0] = seed[1]
seed[1] = seed[2]
seed[2] = temp
}
2020-10-09 22:15:38 +00:00
sub twist(uword x) -> uword {
ubyte xh = msb(x)
ubyte xl = lsb(x)
rol(xh)
rol(xl)
return mkword(xh, xl)
}
sub debug_seed() {
txt.print("\ngalaxy #")
txt.print_ub(number)
txt.print("\ngalaxy seed0=")
txt.print_uwhex(galaxy.seed[0], true)
txt.print("\ngalaxy seed1=")
txt.print_uwhex(galaxy.seed[1], true)
txt.print("\ngalaxy seed2=")
txt.print_uwhex(galaxy.seed[2], true)
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-09 22:15:38 +00:00
}
2020-10-09 20:25:12 +00:00
}
2020-10-04 19:53:16 +00:00
planet {
2020-10-04 15:47:57 +00:00
%option force_output
2020-10-09 22:15:38 +00:00
str[] species_sizes = ["Large", "Fierce", "Small"]
str[] species_colors = ["Green", "Red", "Yellow", "Blue", "Black", "Harmless"]
str[] species_looks = ["Slimy", "Bug-Eyed", "Horned", "Bony", "Fat", "Furry"]
str[] species_kinds = ["Rodents", "Frogs", "Lizards", "Lobsters", "Birds", "Humanoids", "Felines", "Insects"]
2020-10-09 19:01:06 +00:00
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship", "Communist", "Confederacy", "Democracy", "Corporate State"]
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
2020-10-04 15:47:57 +00:00
str[] words81 = ["fabled", "notable", "well known", "famous", "noted"]
str[] words82 = ["very", "mildly", "most", "reasonably", ""]
str[] words83 = ["ancient", "\x95", "great", "vast", "pink"]
str[] words84 = ["\x9E \x9D plantations", "mountains", "\x9C", "\x94 forests", "oceans"]
str[] words85 = ["shyness", "silliness", "mating traditions", "loathing of \x86", "love for \x86"]
str[] words86 = ["food blenders", "tourists", "poetry", "discos", "\x8E"]
str[] words87 = ["talking tree", "crab", "bat", "lobst", "\xB2"]
str[] words88 = ["beset", "plagued", "ravaged", "cursed", "scourged"]
str[] words89 = ["\x96 civil war", "\x9B \x98 \x99s", "a \x9B disease", "\x96 earthquakes", "\x96 solar activity"]
2020-10-05 17:49:13 +00:00
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
2020-10-04 15:47:57 +00:00
str[] words8B = ["juice", "brandy", "water", "brew", "gargle blasters"]
str[] words8C = ["\xB2", "\xB1 \x99", "\xB1 \xB2", "\xB1 \x9B", "\x9B \xB2"]
str[] words8D = ["fabulous", "exotic", "hoopy", "unusual", "exciting"]
str[] words8E = ["cuisine", "night life", "casinos", "sit coms", " \xA1 "]
str[] words8F = ["\xB0", "The planet \xB0", "The world \xB0", "This planet", "This world"]
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
str[] words91 = ["planet", "world", "place", "little planet", "dump"]
str[] words92 = ["wasp", "moth", "grub", "ant", "\xB2"]
str[] words93 = ["poet", "arts graduate", "yak", "snail", "slug"]
str[] words94 = ["tropical", "dense", "rain", "impenetrable", "exuberant"]
str[] words95 = ["funny", "wierd", "unusual", "strange", "peculiar"]
str[] words96 = ["frequent", "occasional", "unpredictable", "dreadful", "deadly"]
2020-10-05 17:49:13 +00:00
str[] words97 = ["\x82 \x81 for \x8A", "\x82 \x81 for \x8A and \x8A", "\x88 by \x89", "\x82 \x81 for \x8A but \x88 by \x89", "a\x90 \x91"]
2020-10-04 15:47:57 +00:00
str[] words98 = ["\x9B", "mountain", "edible", "tree", "spotted"]
str[] words99 = ["\x9F", "\xA0", "\x87oid", "\x93", "\x92"]
str[] words9A = ["ancient", "exceptional", "eccentric", "ingrained", "\x95"]
str[] words9B = ["killer", "deadly", "evil", "lethal", "vicious"]
str[] words9C = ["parking meters", "dust clouds", "ice bergs", "rock formations", "volcanoes"]
str[] words9D = ["plant", "tulip", "banana", "corn", "\xB2weed"]
str[] words9E = ["\xB2", "\xB1 \xB2", "\xB1 \x9B", "inhabitant", "\xB1 \xB2"]
str[] words9F = ["shrew", "beast", "bison", "snake", "wolf"]
str[] wordsA0 = ["leopard", "cat", "monkey", "goat", "fish"]
2020-10-05 17:49:13 +00:00
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
2020-10-04 15:47:57 +00:00
str[] wordsA2 = ["meat", "cutlet", "steak", "burgers", "soup"]
str[] wordsA3 = ["ice", "mud", "Zero-G", "vacuum", "\xB1 ultra"]
str[] wordsA4 = ["hockey", "cricket", "karate", "polo", "tennis"]
uword[] wordlists = [
words81, words82, words83, words84, words85, words86, words87, words88,
words89, words8A, words8B, words8C, words8D, words8E, words8F, words90,
words91, words92, words93, words94, words95, words96, words97, words98,
words99, words9A, words9B, words9C, words9D, words9E, words9F, wordsA0,
wordsA1, wordsA2, wordsA3, wordsA4]
str pairs0 = "abouseitiletstonlonuthnoallexegezacebisousesarmaindirea.eratenbe"
2020-10-09 20:25:12 +00:00
2020-10-04 15:47:57 +00:00
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
2020-10-09 23:29:10 +00:00
str name = " " ; 8 max
ubyte number ; starts at 0 in new galaxy, then increases by 1 for each generated planet
2020-10-09 19:01:06 +00:00
ubyte x
ubyte y
ubyte economy
ubyte govtype
ubyte techlevel
ubyte population
uword productivity
uword radius
2020-10-09 22:15:38 +00:00
ubyte species_is_alien ; otherwise "Human Colonials"
ubyte species_size
ubyte species_color
ubyte species_look
ubyte species_kind
2020-10-04 15:47:57 +00:00
sub set_seed(uword s1, uword s2) {
goatsoup_seed[0] = lsb(s1)
goatsoup_seed[1] = msb(s1)
goatsoup_seed[2] = lsb(s2)
goatsoup_seed[3] = msb(s2)
reset_rnd()
}
sub reset_rnd() {
goatsoup_rnd[0] = goatsoup_seed[0]
goatsoup_rnd[1] = goatsoup_seed[1]
goatsoup_rnd[2] = goatsoup_seed[2]
goatsoup_rnd[3] = goatsoup_seed[3]
}
sub random_name() -> str {
ubyte ii
str name = " " ; 8 chars max
ubyte nx = 0
2020-10-10 22:38:38 +00:00
for ii in 0 to goatsoup_rnd_number() & 3 {
ubyte x = goatsoup_rnd_number() & $3e
2020-10-04 15:47:57 +00:00
if pairs0[x] != '.' {
name[nx] = pairs0[x]
nx++
}
x++
if pairs0[x] != '.' {
name[nx] = pairs0[x]
2020-10-04 15:47:57 +00:00
nx++
}
}
name[nx] = 0
name[0] |= 32 ; uppercase first letter
return name
}
2020-10-10 22:38:38 +00:00
sub goatsoup_rnd_number() -> ubyte {
2020-10-04 15:47:57 +00:00
ubyte x = goatsoup_rnd[0] * 2
uword a = x as uword + goatsoup_rnd[2]
if goatsoup_rnd[0] > 127
a ++
goatsoup_rnd[0] = lsb(a)
goatsoup_rnd[2] = x
x = goatsoup_rnd[1]
ubyte ac = x + goatsoup_rnd[3] + msb(a)
goatsoup_rnd[1] = ac
goatsoup_rnd[3] = x
return ac
}
2020-10-10 14:21:51 +00:00
sub distance(ubyte px, ubyte py) -> ubyte {
uword ax
uword ay
if px>x
ax=px-x
else
ax=x-px
if py>y
ay=py-y
else
ay=y-py
ay /= 2
ubyte d = sqrt16(ax*ax + ay*ay)
if d>63
return 255
return d*4
}
2020-10-04 19:11:57 +00:00
sub soup() -> str {
2020-10-04 19:53:16 +00:00
str planet_result = " " * 160
2020-10-04 19:11:57 +00:00
uword[6] source_stack
ubyte stack_ptr = 0
str start_source = "\x8F is \x97."
uword source_ptr = &start_source
2020-10-04 19:53:16 +00:00
uword result_ptr = &planet_result
2020-10-04 19:11:57 +00:00
2020-10-04 15:47:57 +00:00
reset_rnd()
2020-10-04 19:11:57 +00:00
recursive_soup()
2020-10-04 19:53:16 +00:00
return planet_result
2020-10-04 19:11:57 +00:00
sub recursive_soup() {
repeat {
ubyte c = @(source_ptr)
source_ptr++
if c == $00 {
@(result_ptr) = 0
return
}
else if c <= $80 {
@(result_ptr) = c
result_ptr++
}
else {
if c <= $a4 {
2020-10-10 22:38:38 +00:00
ubyte rnr = goatsoup_rnd_number()
2020-10-04 19:11:57 +00:00
ubyte wordNr = (rnr >= $33) + (rnr >= $66) + (rnr >= $99) + (rnr >= $CC)
source_stack[stack_ptr] = source_ptr
stack_ptr++
source_ptr = getword(c, wordNr)
recursive_soup() ; RECURSIVE CALL - ignore the warning message from the compiler; we don't use local variables or parameters so we're safe in this case
2020-10-04 19:11:57 +00:00
stack_ptr--
source_ptr = source_stack[stack_ptr]
} else {
if c == $b0 {
2020-10-04 19:53:16 +00:00
@(result_ptr) = name[0] | 32
2020-10-04 19:11:57 +00:00
result_ptr++
2020-10-04 19:53:16 +00:00
concat_string(&name + 1)
2020-10-04 19:11:57 +00:00
}
else if c == $b1 {
2020-10-04 19:53:16 +00:00
@(result_ptr) = name[0] | 32
2020-10-04 19:11:57 +00:00
result_ptr++
ubyte ni
2020-10-04 19:53:16 +00:00
for ni in 1 to len(name) {
ubyte cc = name[ni]
2020-10-04 19:11:57 +00:00
if cc=='e' or cc=='o' or cc==0
break
else {
@(result_ptr) = cc
result_ptr++
}
}
@(result_ptr) = 'i'
result_ptr++
@(result_ptr) = 'a'
result_ptr++
@(result_ptr) = 'n'
result_ptr++
}
else if c == $b2 {
2020-10-04 19:53:16 +00:00
concat_string(random_name())
2020-10-04 19:11:57 +00:00
}
else {
@(result_ptr) = c
result_ptr++
}
2020-10-04 15:47:57 +00:00
}
}
}
}
2020-10-04 19:53:16 +00:00
sub concat_string(uword str_ptr) {
repeat {
ubyte c = @(str_ptr)
if c==0
break
else {
@(result_ptr) = c
str_ptr++
result_ptr++
}
}
}
2020-10-04 15:47:57 +00:00
}
2020-10-09 19:01:06 +00:00
sub display(ubyte compressed) {
if compressed {
2020-10-09 20:47:42 +00:00
print_name_uppercase()
2020-10-09 19:01:06 +00:00
txt.print(" TL:")
txt.print_ub(techlevel+1)
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-09 19:01:06 +00:00
txt.print(econnames[economy])
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-09 19:01:06 +00:00
txt.print(govnames[govtype])
} else {
txt.print("\n\nSystem: ")
2020-10-09 20:47:42 +00:00
print_name_uppercase()
2020-10-09 19:01:06 +00:00
txt.print("\nPosition: ")
txt.print_ub(x)
2020-10-09 23:29:10 +00:00
txt.chrout('\'')
2020-10-09 19:01:06 +00:00
txt.print_ub(y)
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-09 23:29:10 +00:00
txt.chrout('#')
txt.print_ub(number)
2020-10-09 19:01:06 +00:00
txt.print("\nEconomy: ")
txt.print(econnames[economy])
txt.print("\nGovernment: ")
txt.print(govnames[govtype])
txt.print("\nTech Level: ")
txt.print_ub(techlevel+1)
txt.print("\nTurnover: ")
txt.print_uw(productivity)
txt.print("\nRadius: ")
txt.print_uw(radius)
2020-10-09 19:01:06 +00:00
txt.print("\nPopulation: ")
txt.print_ub(population >> 3)
2020-10-09 22:15:38 +00:00
txt.print(" Billion\nSpecies: ")
if species_is_alien {
if species_size < len(species_sizes) {
txt.print(species_sizes[species_size])
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-09 22:15:38 +00:00
}
if species_color < len(species_colors) {
txt.print(species_colors[species_color])
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-09 22:15:38 +00:00
}
if species_look < len(species_looks) {
txt.print(species_looks[species_look])
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-09 22:15:38 +00:00
}
if species_kind < len(species_kinds) {
txt.print(species_kinds[species_kind])
}
} else {
txt.print("Human Colonials")
}
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-09 19:01:06 +00:00
txt.print(soup())
2021-01-08 15:56:17 +00:00
txt.nl()
2020-10-09 19:01:06 +00:00
}
}
2020-10-04 19:11:57 +00:00
2020-10-09 20:47:42 +00:00
sub print_name_uppercase() {
ubyte c
for c in name
txt.chrout(c | 32)
}
2020-10-04 19:11:57 +00:00
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
2020-10-04 15:47:57 +00:00
%asm {{
sty P8ZP_SCRATCH_REG
sec
sbc #$81
asl a
tay
lda wordlists,y
sta P8ZP_SCRATCH_W1
lda wordlists+1,y
sta P8ZP_SCRATCH_W1+1
lda P8ZP_SCRATCH_REG
asl a
tay
lda (P8ZP_SCRATCH_W1),y
pha
iny
lda (P8ZP_SCRATCH_W1),y
tay
pla
rts
}}
}
}
2020-10-10 14:21:51 +00:00
util {
2020-10-11 17:26:20 +00:00
sub prefix_matches(uword prefixptr, uword stringptr) -> ubyte {
repeat {
ubyte pc = @(prefixptr)
ubyte sc = @(stringptr)
if pc == 0
return true
; to lowercase for case insensitive compare:
pc &= 127
sc &= 127
if pc != sc
return false
prefixptr++
stringptr++
}
return false
}
sub print_right(ubyte width, uword s) {
repeat width - string.length(s) {
2021-01-14 21:51:09 +00:00
txt.spc()
2020-10-10 21:24:15 +00:00
}
txt.print(s)
2020-10-10 21:24:15 +00:00
}
2020-10-11 17:26:20 +00:00
2020-10-10 22:38:38 +00:00
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
2020-10-10 14:21:51 +00:00
%asm {{
2020-10-14 21:43:38 +00:00
jsr conv.uword2decimal
lda conv.uword2decimal.decTenThousands
ldy #0 ; have we started printing?
cmp #'0'
beq +
jsr c64.CHROUT
iny
2020-10-10 22:38:38 +00:00
+ lda conv.uword2decimal.decThousands
cmp #'0'
2020-10-11 17:26:20 +00:00
bne +
cpy #0
beq ++
+ jsr c64.CHROUT
iny
2020-10-10 22:38:38 +00:00
+ lda conv.uword2decimal.decHundreds
cmp #'0'
2020-10-11 17:26:20 +00:00
bne +
cpy #0
beq ++
+ jsr c64.CHROUT
iny
2020-10-10 22:38:38 +00:00
+ lda conv.uword2decimal.decTens
2020-10-10 14:21:51 +00:00
jsr c64.CHROUT
lda #'.'
jsr c64.CHROUT
2020-10-10 22:38:38 +00:00
lda conv.uword2decimal.decOnes
2020-10-10 14:21:51 +00:00
jsr c64.CHROUT
2020-10-10 22:38:38 +00:00
rts
2020-10-10 14:21:51 +00:00
}}
}
}