mirror of
https://github.com/irmen/prog8.git
synced 2024-06-13 09:29:34 +00:00
removed support for structs. It was too much hassle and complexity and subtle bugs.
This commit is contained in:
parent
1bde7c7718
commit
a9a7068818
|
@ -36,7 +36,6 @@ What does Prog8 provide?
|
|||
- conditional branches
|
||||
- floating point operations (requires the C64 Basic ROM routines for this)
|
||||
- 'when' statement to provide a concise jump table alternative to if/elseif chains
|
||||
- structs to group together sets of variables and manipulate them at once
|
||||
- many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``sort`` and ``reverse``
|
||||
- various powerful built-in libraries to do I/O, number conversions, graphics and more
|
||||
- convenience abstractions for low level aspects such as ZeroPage handling, program startup, explicit memory addresses
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package prog8.compiler
|
||||
|
||||
import prog8.ast.IFunctionCall
|
||||
import prog8.ast.INameScope
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
|
@ -84,6 +83,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I
|
|||
val sub = scope.definingSubroutine()
|
||||
if (sub != null) {
|
||||
// move vardecls of the scope into the upper scope. Make sure the position remains the same!
|
||||
// TODO THIS HAS ALREADY BEEN TAKEN CARE OF AT THE START????
|
||||
val replacements = mutableListOf<IAstModification>()
|
||||
val movements = mutableListOf<IAstModification.InsertFirst>()
|
||||
|
||||
|
|
|
@ -317,7 +317,7 @@ private fun writeAssembly(programAst: Program,
|
|||
programAst.processAstBeforeAsmGeneration(errors, compilerOptions.compTarget)
|
||||
errors.report()
|
||||
|
||||
// printAst(programAst)
|
||||
printAst(programAst)
|
||||
|
||||
compilerOptions.compTarget.machine.initializeZeropage(compilerOptions)
|
||||
val assembly = asmGeneratorFor(compilerOptions.compTarget,
|
||||
|
|
|
@ -418,30 +418,6 @@ internal class AstChecker(private val program: Program,
|
|||
}
|
||||
}
|
||||
|
||||
val targetIdent = assignment.target.identifier
|
||||
if(targetIdent!=null) {
|
||||
val targetVar = targetIdent.targetVarDecl(program)
|
||||
if(targetVar?.struct != null) {
|
||||
val sourceStructLv = assignment.value as? ArrayLiteralValue
|
||||
if (sourceStructLv != null) {
|
||||
if (sourceStructLv.value.size != targetVar.struct?.numberOfElements)
|
||||
errors.err("number of elements doesn't match struct definition", sourceStructLv.position)
|
||||
} else {
|
||||
val sourceIdent = assignment.value as? IdentifierReference
|
||||
if (sourceIdent != null) {
|
||||
val sourceVar = sourceIdent.targetVarDecl(program)
|
||||
if (sourceVar?.struct != null) {
|
||||
if (sourceVar.struct !== targetVar.struct)
|
||||
errors.err("assignment of different struct types", assignment.position)
|
||||
} else if(sourceVar?.isArray==true) {
|
||||
if((sourceVar.value as ArrayLiteralValue).value.size != targetVar.struct?.numberOfElements)
|
||||
errors.err("number of elements doesn't match struct definition", sourceVar.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val targetDt = assignment.target.inferType(program)
|
||||
val valueDt = assignment.value.inferType(program)
|
||||
if(valueDt.isKnown && !(valueDt isAssignableTo targetDt)) {
|
||||
|
@ -561,17 +537,6 @@ internal class AstChecker(private val program: Program,
|
|||
|
||||
when(decl.type) {
|
||||
VarDeclType.VAR, VarDeclType.CONST -> {
|
||||
if(decl.datatype==DataType.STRUCT) {
|
||||
if(decl.struct==null)
|
||||
throw FatalAstException("struct vardecl should be linked to its struct $decl")
|
||||
if(decl.zeropage==ZeropageWish.PREFER_ZEROPAGE || decl.zeropage==ZeropageWish.REQUIRE_ZEROPAGE)
|
||||
err("struct can not be in zeropage")
|
||||
}
|
||||
if(decl.struct!=null) {
|
||||
if(decl.zeropage==ZeropageWish.PREFER_ZEROPAGE || decl.zeropage==ZeropageWish.REQUIRE_ZEROPAGE)
|
||||
err("struct can not be in zeropage")
|
||||
}
|
||||
|
||||
when(decl.value) {
|
||||
null -> {
|
||||
// a vardecl without an initial value, don't bother with it
|
||||
|
@ -581,30 +546,8 @@ internal class AstChecker(private val program: Program,
|
|||
checkValueTypeAndRangeString(decl.datatype, decl.value as StringLiteralValue)
|
||||
}
|
||||
is ArrayLiteralValue -> {
|
||||
if(decl.datatype==DataType.STRUCT) {
|
||||
val struct = decl.struct!!
|
||||
val structLv = decl.value as ArrayLiteralValue
|
||||
if(struct.numberOfElements != structLv.value.size) {
|
||||
errors.err("struct value has incorrect number of elements", structLv.position)
|
||||
return
|
||||
}
|
||||
for(value in structLv.value.zip(struct.statements)) {
|
||||
val memberdecl = value.second as VarDecl
|
||||
val constValue = value.first.constValue(program)
|
||||
if(constValue==null) {
|
||||
errors.err("struct literal value for field '${memberdecl.name}' should consist of compile-time constants", value.first.position)
|
||||
return
|
||||
}
|
||||
val memberDt = memberdecl.datatype
|
||||
if(!checkValueTypeAndRange(memberDt, constValue)) {
|
||||
errors.err("type of struct member value is not compatible with member field '${memberdecl.name}'", value.first.position)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val arraySpec = decl.arraysize ?: ArrayIndex.forArray(decl.value as ArrayLiteralValue)
|
||||
checkValueTypeAndRangeArray(decl.datatype, decl.struct, arraySpec, decl.value as ArrayLiteralValue)
|
||||
}
|
||||
val arraySpec = decl.arraysize ?: ArrayIndex.forArray(decl.value as ArrayLiteralValue)
|
||||
checkValueTypeAndRangeArray(decl.datatype, arraySpec, decl.value as ArrayLiteralValue)
|
||||
}
|
||||
is NumericLiteralValue -> {
|
||||
checkValueTypeAndRange(decl.datatype, decl.value as NumericLiteralValue)
|
||||
|
@ -648,14 +591,7 @@ internal class AstChecker(private val program: Program,
|
|||
|
||||
val declValue = decl.value
|
||||
if(declValue!=null && decl.type==VarDeclType.VAR) {
|
||||
if(decl.datatype==DataType.STRUCT) {
|
||||
val valueIdt = declValue.inferType(program)
|
||||
if(!valueIdt.isKnown)
|
||||
throw AstException("unknown dt")
|
||||
val valueDt = valueIdt.typeOrElse(DataType.STRUCT)
|
||||
if(valueDt !in ArrayDatatypes)
|
||||
err("initialisation of struct should be with array value", declValue.position)
|
||||
} else if (!declValue.inferType(program).istype(decl.datatype)) {
|
||||
if (!declValue.inferType(program).istype(decl.datatype)) {
|
||||
err("initialisation value has incompatible type (${declValue.inferType(program)}) for the variable (${decl.datatype})", declValue.position)
|
||||
}
|
||||
}
|
||||
|
@ -803,7 +739,7 @@ internal class AstChecker(private val program: Program,
|
|||
errors.err("floating point used, but that is not enabled via options", array.position)
|
||||
}
|
||||
val arrayspec = ArrayIndex.forArray(array)
|
||||
checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.STRUCT), null, arrayspec, array)
|
||||
checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.STRUCT), arrayspec, array)
|
||||
}
|
||||
|
||||
fun isPassByReferenceElement(e: Expression): Boolean {
|
||||
|
@ -1209,24 +1145,6 @@ internal class AstChecker(private val program: Program,
|
|||
super.visit(whenChoice)
|
||||
}
|
||||
|
||||
override fun visit(structDecl: StructDecl) {
|
||||
// a struct can only contain 1 or more vardecls and can not be nested
|
||||
if(structDecl.statements.isEmpty())
|
||||
errors.err("struct must contain at least one member", structDecl.position)
|
||||
|
||||
for(member in structDecl.statements){
|
||||
val decl = member as? VarDecl
|
||||
if(decl==null)
|
||||
errors.err("struct can only contain variable declarations", structDecl.position)
|
||||
else {
|
||||
if(decl.zeropage==ZeropageWish.REQUIRE_ZEROPAGE || decl.zeropage==ZeropageWish.PREFER_ZEROPAGE)
|
||||
errors.err("struct can not contain zeropage members", decl.position)
|
||||
if(decl.datatype !in NumericDatatypes)
|
||||
errors.err("structs can only contain numerical types", decl.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkFunctionOrLabelExists(target: IdentifierReference, statement: Statement): Statement? {
|
||||
val targetStatement = target.targetStatement(program)
|
||||
if(targetStatement is Label || targetStatement is Subroutine || targetStatement is BuiltinFunctionStatementPlaceholder)
|
||||
|
@ -1250,8 +1168,7 @@ internal class AstChecker(private val program: Program,
|
|||
else false
|
||||
}
|
||||
|
||||
private fun checkValueTypeAndRangeArray(targetDt: DataType, struct: StructDecl?,
|
||||
arrayspec: ArrayIndex, value: ArrayLiteralValue) : Boolean {
|
||||
private fun checkValueTypeAndRangeArray(targetDt: DataType, arrayspec: ArrayIndex, value: ArrayLiteralValue) : Boolean {
|
||||
fun err(msg: String) : Boolean {
|
||||
errors.err(msg, value.position)
|
||||
return false
|
||||
|
@ -1324,22 +1241,6 @@ internal class AstChecker(private val program: Program,
|
|||
}
|
||||
return err("invalid float array initialization value ${value.type}, expected $targetDt")
|
||||
}
|
||||
DataType.STRUCT -> {
|
||||
if(value.type.typeOrElse(DataType.STRUCT) in ArrayDatatypes) {
|
||||
if(value.value.size != struct!!.numberOfElements)
|
||||
return err("number of values is not the same as the number of members in the struct")
|
||||
for(elt in value.value.zip(struct.statements)) {
|
||||
val vardecl = elt.second as VarDecl
|
||||
val valuetype = elt.first.inferType(program)
|
||||
if (!valuetype.isKnown || valuetype isNotAssignableTo vardecl.datatype) {
|
||||
errors.err("invalid struct member init value type $valuetype, expected ${vardecl.datatype}", elt.first.position)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
|
@ -1442,15 +1343,6 @@ internal class AstChecker(private val program: Program,
|
|||
DataType.UWORD -> sourceDatatype== DataType.UBYTE || sourceDatatype== DataType.UWORD
|
||||
DataType.FLOAT -> sourceDatatype in NumericDatatypes
|
||||
DataType.STR -> sourceDatatype== DataType.STR
|
||||
DataType.STRUCT -> {
|
||||
if(sourceDatatype==DataType.STRUCT) {
|
||||
val structLv = sourceValue as ArrayLiteralValue
|
||||
val numValues = structLv.value.size
|
||||
val targetstruct = target.identifier!!.targetVarDecl(program)!!.struct!!
|
||||
return targetstruct.numberOfElements == numValues
|
||||
}
|
||||
false
|
||||
}
|
||||
else -> {
|
||||
errors.err("cannot assign new value to variable of type $targetDatatype", position)
|
||||
false
|
||||
|
|
|
@ -2,11 +2,7 @@ package prog8.compiler.astprocessing
|
|||
|
||||
import prog8.ast.Module
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.NumericDatatypes
|
||||
import prog8.ast.base.Position
|
||||
import prog8.ast.expressions.ArrayLiteralValue
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.expressions.StringLiteralValue
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
|
@ -66,29 +62,6 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
|||
if(decl.name in compTarget.machine.opcodeNames)
|
||||
errors.err("can't use a cpu opcode name as a symbol: '${decl.name}'", decl.position)
|
||||
|
||||
if(decl.datatype==DataType.STRUCT) {
|
||||
if (decl.structHasBeenFlattened)
|
||||
return super.visit(decl) // don't do this multiple times
|
||||
|
||||
if (decl.struct == null) {
|
||||
errors.err("undefined struct type", decl.position)
|
||||
return super.visit(decl)
|
||||
}
|
||||
|
||||
if (decl.struct!!.statements.any { (it as VarDecl).datatype !in NumericDatatypes })
|
||||
return super.visit(decl) // a non-numeric member, not supported. proper error is given by AstChecker later
|
||||
|
||||
if (decl.value is NumericLiteralValue) {
|
||||
errors.err("you cannot initialize a struct using a single value", decl.position)
|
||||
return super.visit(decl)
|
||||
}
|
||||
|
||||
if (decl.value != null && decl.value !is ArrayLiteralValue) {
|
||||
errors.err("initializing a struct requires array literal value", decl.value?.position ?: decl.position)
|
||||
return super.visit(decl)
|
||||
}
|
||||
}
|
||||
|
||||
val existing = program.namespace.lookup(listOf(decl.name), decl)
|
||||
if (existing != null && existing !== decl)
|
||||
nameError(decl.name, decl.position, existing)
|
||||
|
@ -169,14 +142,4 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
|||
|
||||
super.visit(string)
|
||||
}
|
||||
|
||||
override fun visit(structDecl: StructDecl) {
|
||||
for(member in structDecl.statements){
|
||||
val decl = member as? VarDecl
|
||||
if(decl!=null && decl.datatype !in NumericDatatypes)
|
||||
errors.err("structs can only contain numerical types", decl.position)
|
||||
}
|
||||
|
||||
super.visit(structDecl)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,8 @@ package prog8.compiler.astprocessing
|
|||
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.StringLiteralValue
|
||||
import prog8.ast.statements.AnonymousScope
|
||||
import prog8.ast.statements.ParameterVarDecl
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.VarDecl
|
||||
|
@ -15,19 +13,6 @@ import prog8.ast.walk.IAstModification
|
|||
|
||||
internal class AstVariousTransforms(private val program: Program) : AstWalker() {
|
||||
|
||||
override fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||
// is it a struct variable? then define all its struct members as mangled names,
|
||||
// and include the original decl as well.
|
||||
if(decl.datatype==DataType.STRUCT && !decl.structHasBeenFlattened) {
|
||||
val decls = decl.flattenStructMembers()
|
||||
decls.add(decl)
|
||||
val result = AnonymousScope(decls, decl.position)
|
||||
return listOf(IAstModification.ReplaceNode(decl, result, parent))
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
|
||||
// For non-kernal subroutines and non-asm parameters:
|
||||
// inject subroutine params as local variables (if they're not there yet).
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
package prog8.compiler.astprocessing
|
||||
|
||||
import prog8.ast.*
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.IFunctionCall
|
||||
import prog8.ast.Module
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.ArrayDatatypes
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
|
@ -18,7 +23,6 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
|
|||
// - in every block and module, most directives and vardecls are moved to the top. (not in subroutines!)
|
||||
// - the 'start' subroutine is moved to the top.
|
||||
// - (syntax desugaring) a vardecl with a non-const initializer value is split into a regular vardecl and an assignment statement.
|
||||
// - (syntax desugaring) struct value assignment is expanded into several struct member assignments.
|
||||
// - in-place assignments are reordered a bit so that they are mostly of the form A = A <operator> <rest>
|
||||
// - sorts the choices in when statement.
|
||||
// - insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
||||
|
@ -200,40 +204,10 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
|
|||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||
val declValue = decl.value
|
||||
if(declValue!=null && decl.type== VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
||||
val declConstValue = declValue.constValue(program)
|
||||
if(declConstValue==null) {
|
||||
val subroutine = decl.definingSubroutine() as? INameScope
|
||||
if(subroutine!=null) {
|
||||
// move the vardecl (without value) to the scope of the defining subroutine and put a regular assignment in its place here.
|
||||
decl.value = null
|
||||
decl.allowInitializeWithZero = false
|
||||
val target = AssignTarget(IdentifierReference(listOf(decl.name), decl.position), null, null, decl.position)
|
||||
val assign = Assignment(target, declValue, decl.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(decl, assign, parent),
|
||||
IAstModification.InsertFirst(decl, subroutine)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||
val valueType = assignment.value.inferType(program)
|
||||
val targetType = assignment.target.inferType(program)
|
||||
|
||||
if(targetType.istype(DataType.STRUCT) && (valueType.istype(DataType.STRUCT) || valueType.typeOrElse(DataType.STRUCT) in ArrayDatatypes )) {
|
||||
if (assignment.value is ArrayLiteralValue) {
|
||||
errors.err("cannot assign array literal here, use separate assignment per field", assignment.position)
|
||||
} else {
|
||||
return copyStructValue(assignment)
|
||||
}
|
||||
}
|
||||
|
||||
if(targetType.typeOrElse(DataType.STRUCT) in ArrayDatatypes && valueType.typeOrElse(DataType.STRUCT) in ArrayDatatypes ) {
|
||||
if (assignment.value is ArrayLiteralValue) {
|
||||
errors.err("cannot assign array literal here, use separate assignment per element", assignment.position)
|
||||
|
@ -330,73 +304,4 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
|
|||
)
|
||||
return listOf(IAstModification.ReplaceNode(assign, memcopy, assign.parent))
|
||||
}
|
||||
|
||||
private fun copyStructValue(structAssignment: Assignment): List<IAstModification> {
|
||||
val identifier = structAssignment.target.identifier!!
|
||||
val targetVar = identifier.targetVarDecl(program)!!
|
||||
val struct = targetVar.struct!!
|
||||
when (structAssignment.value) {
|
||||
is IdentifierReference -> {
|
||||
val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program)!!
|
||||
val memsize = struct.memsize(program.memsizer)
|
||||
when {
|
||||
sourceVar.struct!=null -> {
|
||||
// struct memberwise copy
|
||||
val sourceStruct = sourceVar.struct!!
|
||||
if(sourceStruct!==targetVar.struct) {
|
||||
errors.err("struct type mismatch", structAssignment.position)
|
||||
return listOf()
|
||||
}
|
||||
if(struct.statements.size!=sourceStruct.statements.size) {
|
||||
errors.err("struct element count mismatch", structAssignment.position)
|
||||
return listOf()
|
||||
}
|
||||
if(memsize!=sourceStruct.memsize(program.memsizer)) {
|
||||
errors.err("memory size mismatch", structAssignment.position)
|
||||
return listOf()
|
||||
}
|
||||
val memcopy = FunctionCallStatement(IdentifierReference(listOf("sys", "memcopy"), structAssignment.position),
|
||||
mutableListOf(
|
||||
AddressOf(structAssignment.value as IdentifierReference, structAssignment.position),
|
||||
AddressOf(identifier, structAssignment.position),
|
||||
NumericLiteralValue.optimalInteger(memsize, structAssignment.position)
|
||||
),
|
||||
true,
|
||||
structAssignment.position
|
||||
)
|
||||
return listOf(IAstModification.ReplaceNode(structAssignment, memcopy, structAssignment.parent))
|
||||
}
|
||||
sourceVar.isArray -> {
|
||||
val array = sourceVar.value as ArrayLiteralValue
|
||||
if(struct.statements.size!=array.value.size) {
|
||||
errors.err("struct element count mismatch", structAssignment.position)
|
||||
return listOf()
|
||||
}
|
||||
if(memsize!=array.memsize(program.memsizer)) {
|
||||
errors.err("memory size mismatch", structAssignment.position)
|
||||
return listOf()
|
||||
}
|
||||
val memcopy = FunctionCallStatement(IdentifierReference(listOf("sys", "memcopy"), structAssignment.position),
|
||||
mutableListOf(
|
||||
AddressOf(structAssignment.value as IdentifierReference, structAssignment.position),
|
||||
AddressOf(identifier, structAssignment.position),
|
||||
NumericLiteralValue.optimalInteger(memsize, structAssignment.position)
|
||||
),
|
||||
true,
|
||||
structAssignment.position
|
||||
)
|
||||
return listOf(IAstModification.ReplaceNode(structAssignment, memcopy, structAssignment.parent))
|
||||
}
|
||||
else -> {
|
||||
throw FatalAstException("can only assign arrays or structs to structs")
|
||||
}
|
||||
}
|
||||
}
|
||||
is ArrayLiteralValue -> {
|
||||
throw IllegalArgumentException("not going to do a structLv assignment here")
|
||||
}
|
||||
else -> throw FatalAstException("strange struct value")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
|
|||
|
||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||
val declValue = decl.value
|
||||
if(decl.type==VarDeclType.VAR && declValue!=null && decl.struct==null) {
|
||||
if(decl.type==VarDeclType.VAR && declValue!=null) {
|
||||
val valueDt = declValue.inferType(program)
|
||||
if(!valueDt.istype(decl.datatype)) {
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import prog8.ast.IMemSizer
|
|||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.StructDecl
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.compiler.CompilerException
|
||||
import kotlin.math.*
|
||||
|
@ -105,7 +104,6 @@ private val functionSignatures: List<FSignature> = listOf(
|
|||
FSignature("abs" , true, listOf(FParam("value", NumericDatatypes)), null, ::builtinAbs), // type depends on argument
|
||||
FSignature("len" , true, listOf(FParam("values", IterableDatatypes)), null, ::builtinLen), // type is UBYTE or UWORD depending on actual length
|
||||
FSignature("sizeof" , true, listOf(FParam("object", DataType.values().toSet())), DataType.UBYTE, ::builtinSizeof),
|
||||
FSignature("offsetof" , true, listOf(FParam("object", DataType.values().toSet())), DataType.UBYTE, ::builtinOffsetof),
|
||||
// normal functions follow:
|
||||
FSignature("sgn" , true, listOf(FParam("value", NumericDatatypes)), DataType.BYTE, ::builtinSgn ),
|
||||
FSignature("sin" , true, listOf(FParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg, ct -> oneDoubleArg(a, p, prg, Math::sin) },
|
||||
|
@ -289,28 +287,6 @@ private fun builtinAbs(args: List<Expression>, position: Position, program: Prog
|
|||
}
|
||||
}
|
||||
|
||||
private fun builtinOffsetof(args: List<Expression>, position: Position, program: Program, memsizer: IMemSizer): NumericLiteralValue {
|
||||
// 1 arg, type = anything, result type = ubyte
|
||||
if(args.size!=1)
|
||||
throw SyntaxError("offsetof requires one argument", position)
|
||||
val idref = args[0] as? IdentifierReference
|
||||
?: throw SyntaxError("offsetof argument should be an identifier", position)
|
||||
|
||||
val vardecl = idref.targetVarDecl(program)!!
|
||||
val struct = vardecl.struct
|
||||
if (struct == null || vardecl.datatype == DataType.STRUCT)
|
||||
throw SyntaxError("offsetof can only be used on struct members", position)
|
||||
|
||||
val membername = idref.nameInSource.last()
|
||||
var offset = 0
|
||||
for(member in struct.statements) {
|
||||
if((member as VarDecl).name == membername)
|
||||
return NumericLiteralValue(DataType.UBYTE, offset, position)
|
||||
offset += memsizer.memorySize(member.datatype)
|
||||
}
|
||||
throw SyntaxError("undefined struct member", position)
|
||||
}
|
||||
|
||||
private fun builtinSizeof(args: List<Expression>, position: Position, program: Program, memsizer: IMemSizer): NumericLiteralValue {
|
||||
// 1 arg, type = anything, result type = ubyte
|
||||
if(args.size!=1)
|
||||
|
@ -323,21 +299,12 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
|
|||
val target = (args[0] as IdentifierReference).targetStatement(program)
|
||||
?: throw CannotEvaluateException("sizeof", "no target")
|
||||
|
||||
fun structSize(target: StructDecl) = NumericLiteralValue(DataType.UBYTE, target.memsize(memsizer), position)
|
||||
|
||||
return when {
|
||||
dt.typeOrElse(DataType.STRUCT) in ArrayDatatypes -> {
|
||||
val length = (target as VarDecl).arraysize!!.constIndex() ?: throw CannotEvaluateException("sizeof", "unknown array size")
|
||||
val elementDt = ArrayElementTypes.getValue(dt.typeOrElse(DataType.STRUCT))
|
||||
numericLiteral(memsizer.memorySize(elementDt) * length, position)
|
||||
}
|
||||
dt.istype(DataType.STRUCT) -> {
|
||||
when (target) {
|
||||
is VarDecl -> structSize(target.struct!!)
|
||||
is StructDecl -> structSize(target)
|
||||
else -> throw CompilerException("weird struct type $target")
|
||||
}
|
||||
}
|
||||
dt.istype(DataType.STR) -> throw SyntaxError("sizeof str is undefined, did you mean len?", position)
|
||||
else -> NumericLiteralValue(DataType.UBYTE, memsizer.memorySize(dt.typeOrElse(DataType.STRUCT)), position)
|
||||
}
|
||||
|
@ -374,7 +341,6 @@ private fun builtinLen(args: List<Expression>, position: Position, program: Prog
|
|||
val refLv = target.value as? StringLiteralValue ?: throw CannotEvaluateException("len", "stringsize unknown")
|
||||
NumericLiteralValue.optimalInteger(refLv.value.length, args[0].position)
|
||||
}
|
||||
DataType.STRUCT -> throw SyntaxError("cannot use len on struct, did you mean sizeof?", args[0].position)
|
||||
in NumericDatatypes -> throw SyntaxError("cannot use len on numeric value, did you mean sizeof?", args[0].position)
|
||||
else -> throw CompilerException("weird datatype")
|
||||
}
|
||||
|
|
|
@ -379,14 +379,8 @@ internal class AsmGen(private val program: Program,
|
|||
out("\n; non-zeropage variables")
|
||||
val vars = statements.filterIsInstance<VarDecl>().filter { it.type==VarDeclType.VAR }
|
||||
|
||||
// first output the flattened struct member variables *in order*
|
||||
// after that, the other variables sorted by their datatype
|
||||
|
||||
val (structMembers, normalVars) = vars.partition { it.struct!=null }
|
||||
structMembers.forEach { vardecl2asm(it) }
|
||||
|
||||
// special treatment for string types: merge strings that are identical
|
||||
val encodedstringVars = normalVars
|
||||
val encodedstringVars = vars
|
||||
.filter {it.datatype == DataType.STR }
|
||||
.map {
|
||||
val str = it.value as StringLiteralValue
|
||||
|
@ -400,7 +394,7 @@ internal class AsmGen(private val program: Program,
|
|||
}
|
||||
|
||||
// non-string variables
|
||||
normalVars.filter{ it.datatype != DataType.STR }.sortedBy { it.datatype }.forEach {
|
||||
vars.filter{ it.datatype != DataType.STR }.sortedBy { it.datatype }.forEach {
|
||||
if(it.makeScopedName(it.name) !in allocatedZeropageVariables)
|
||||
vardecl2asm(it)
|
||||
}
|
||||
|
@ -437,10 +431,10 @@ internal class AsmGen(private val program: Program,
|
|||
"$" + it.number.toInt().toString(16).padStart(4, '0')
|
||||
}
|
||||
is AddressOf -> {
|
||||
it.identifier.firstStructVarName(program) ?: asmSymbolName(it.identifier)
|
||||
asmSymbolName(it.identifier)
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
it.firstStructVarName(program) ?: asmSymbolName(it)
|
||||
asmSymbolName(it)
|
||||
}
|
||||
else -> throw AssemblyError("weird array elt dt")
|
||||
}
|
||||
|
@ -501,14 +495,8 @@ internal class AsmGen(private val program: Program,
|
|||
return newName
|
||||
}
|
||||
|
||||
internal fun asmSymbolName(identifier: IdentifierReference): String {
|
||||
return if(identifier.memberOfStruct(program)!=null) {
|
||||
val name = identifier.targetVarDecl(program)!!.name
|
||||
fixNameSymbols(name)
|
||||
} else {
|
||||
fixNameSymbols(identifier.nameInSource.joinToString("."))
|
||||
}
|
||||
}
|
||||
internal fun asmSymbolName(identifier: IdentifierReference) =
|
||||
fixNameSymbols(identifier.nameInSource.joinToString("."))
|
||||
|
||||
internal fun asmSymbolName(regs: RegisterOrPair): String =
|
||||
if(regs in Cx16VirtualRegisters)
|
||||
|
@ -516,14 +504,8 @@ internal class AsmGen(private val program: Program,
|
|||
else
|
||||
throw AssemblyError("no symbol name for register $regs")
|
||||
|
||||
internal fun asmVariableName(identifier: IdentifierReference): String {
|
||||
return if(identifier.memberOfStruct(program)!=null) {
|
||||
val name = identifier.targetVarDecl(program)!!.name
|
||||
fixNameSymbols(name)
|
||||
} else {
|
||||
fixNameSymbols(identifier.nameInSource.joinToString("."))
|
||||
}
|
||||
}
|
||||
internal fun asmVariableName(identifier: IdentifierReference) =
|
||||
fixNameSymbols(identifier.nameInSource.joinToString("."))
|
||||
|
||||
internal fun asmSymbolName(name: String) = fixNameSymbols(name)
|
||||
internal fun asmVariableName(name: String) = fixNameSymbols(name)
|
||||
|
@ -671,7 +653,7 @@ internal class AsmGen(private val program: Program,
|
|||
when(stmt) {
|
||||
is ParameterVarDecl -> { /* subroutine parameter vardecls don't get any special treatment here */ }
|
||||
is VarDecl -> translate(stmt)
|
||||
is StructDecl, is NopStatement -> {}
|
||||
is NopStatement -> {}
|
||||
is Directive -> translate(stmt)
|
||||
is Return -> translate(stmt)
|
||||
is Subroutine -> translateSubroutine(stmt)
|
||||
|
|
|
@ -145,7 +145,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||
SourceStorageKind.EXPRESSION -> {
|
||||
when(val value = assign.source.expression!!) {
|
||||
is AddressOf -> {
|
||||
val sourceName = value.identifier.firstStructVarName(program) ?: asmgen.asmVariableName(value.identifier)
|
||||
val sourceName = asmgen.asmVariableName(value.identifier)
|
||||
assignAddressOf(assign.target, sourceName)
|
||||
}
|
||||
is NumericLiteralValue -> throw AssemblyError("source kind should have been literalnumber")
|
||||
|
|
|
@ -3,7 +3,8 @@ package prog8.optimizer
|
|||
import prog8.ast.INameScope
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.augmentAssignmentOperators
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.walk.AstWalker
|
||||
|
|
|
@ -175,7 +175,7 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
|||
}
|
||||
|
||||
fun unused(decl: VarDecl): Boolean {
|
||||
if(decl.type!=VarDeclType.VAR || decl.datatype==DataType.STRUCT || decl.autogeneratedDontRemove || decl.parent is StructDecl)
|
||||
if(decl.type!=VarDeclType.VAR || decl.datatype==DataType.STRUCT || decl.autogeneratedDontRemove)
|
||||
return false
|
||||
|
||||
if(decl.definingBlock() !in usedBlocks)
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package prog8.optimizer
|
||||
|
||||
import prog8.ast.INameScope
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.ArrayIndex
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.ForLoop
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.compiler.IErrorReporter
|
||||
|
@ -30,6 +28,28 @@ internal class VarConstantValueTypeAdjuster(private val program: Program, privat
|
|||
errors.err(x.message, x.position)
|
||||
}
|
||||
|
||||
// move a vardecl to the scope of the defining subroutine and put a regular assignment in its place here (if it has a value)
|
||||
if(decl.type== VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
||||
val subroutine = decl.definingSubroutine() as? INameScope
|
||||
if(subroutine!=null) {
|
||||
val declValue = decl.value
|
||||
decl.value = null
|
||||
decl.allowInitializeWithZero = false
|
||||
return if(declValue==null) {
|
||||
listOf(
|
||||
IAstModification.Remove(decl, parent as INameScope),
|
||||
IAstModification.InsertFirst(decl, subroutine)
|
||||
)
|
||||
} else {
|
||||
val target = AssignTarget(IdentifierReference(listOf(decl.name), decl.position), null, null, decl.position)
|
||||
val assign = Assignment(target, declValue, decl.position)
|
||||
listOf(
|
||||
IAstModification.ReplaceNode(decl, assign, parent),
|
||||
IAstModification.InsertFirst(decl, subroutine)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +209,6 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
|
|||
}
|
||||
else -> {
|
||||
// nothing to do for this type
|
||||
// this includes strings and structs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ internal class StatementOptimizer(private val program: Program,
|
|||
|
||||
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
|
||||
for(returnvar in subsThatNeedReturnVariable) {
|
||||
val decl = VarDecl(VarDeclType.VAR, returnvar.second, ZeropageWish.DONTCARE, null, retvarName, null, null, false, true, returnvar.third)
|
||||
val decl = VarDecl(VarDeclType.VAR, returnvar.second, ZeropageWish.DONTCARE, null, retvarName, null, false, true, returnvar.third)
|
||||
returnvar.first.statements.add(0, decl)
|
||||
}
|
||||
subsThatNeedReturnVariable.clear()
|
||||
|
|
|
@ -52,7 +52,7 @@ internal class UnusedCodeRemover(private val program: Program,
|
|||
|
||||
private fun reportUnreachable(stmt: Statement, parent: INameScope) {
|
||||
when(val next = parent.nextSibling(stmt)) {
|
||||
null, is Label, is Directive, is VarDecl, is InlineAssembly, is Subroutine, is StructDecl -> {}
|
||||
null, is Label, is Directive, is VarDecl, is InlineAssembly, is Subroutine -> {}
|
||||
else -> errors.warn("unreachable code", next.position)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE
|
|||
import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5
|
||||
import prog8.compiler.target.cbm.Petscii
|
||||
import prog8.compiler.target.cx16.CX16MachineDefinition.CX16Zeropage
|
||||
import java.io.CharConversionException
|
||||
import java.nio.file.Path
|
||||
import kotlin.test.*
|
||||
|
||||
|
@ -503,7 +502,7 @@ class TestMemory {
|
|||
|
||||
@Test
|
||||
private fun createTestProgramForMemoryRefViaVar(address: Int, vartype: VarDeclType): AssignTarget {
|
||||
val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val memexpr = IdentifierReference(listOf("address"), Position.DUMMY)
|
||||
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||
|
@ -523,7 +522,7 @@ class TestMemory {
|
|||
|
||||
@Test
|
||||
fun testInValidRamC64_variable() {
|
||||
val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, null, false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
|
@ -536,7 +535,7 @@ class TestMemory {
|
|||
@Test
|
||||
fun testInValidRamC64_memmap_variable() {
|
||||
val address = 0x1000
|
||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
|
@ -549,7 +548,7 @@ class TestMemory {
|
|||
@Test
|
||||
fun testNotInValidRamC64_memmap_variable() {
|
||||
val address = 0xd020
|
||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
|
@ -561,7 +560,7 @@ class TestMemory {
|
|||
|
||||
@Test
|
||||
fun testInValidRamC64_array() {
|
||||
val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, null, false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, Position.DUMMY)
|
||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||
|
@ -575,7 +574,7 @@ class TestMemory {
|
|||
@Test
|
||||
fun testInValidRamC64_array_memmapped() {
|
||||
val address = 0x1000
|
||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||
|
@ -589,7 +588,7 @@ class TestMemory {
|
|||
@Test
|
||||
fun testNotValidRamC64_array_memmapped() {
|
||||
val address = 0xe000
|
||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||
|
|
|
@ -1,993 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy10 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf10 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet10 in galaxy10 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy10.travel_to(1, numforLave)
|
||||
market10.init(0) ; Lave's market10 is seeded with 0
|
||||
ship10.init()
|
||||
planet10.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util10.print_10s(ship10.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market10 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader10.do_buy()
|
||||
's' -> trader10.do_sell()
|
||||
'f' -> trader10.do_fuel()
|
||||
'j' -> trader10.do_jump()
|
||||
't' -> trader10.do_teleport()
|
||||
'g' -> trader10.do_next_galaxy10()
|
||||
'i' -> trader10.do_info()
|
||||
'm' -> trader10.do_show_market10()
|
||||
'l' -> trader10.do_local()
|
||||
'c' -> trader10.do_cash()
|
||||
'h' -> trader10.do_hold()
|
||||
'<' -> trader10.do_load()
|
||||
'>' -> trader10.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader10 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy10
|
||||
ubyte planet10
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship10.cash = savedata.cash
|
||||
ship10.Max_cargo = savedata.max_cargo
|
||||
ship10.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship10.cargohold, len(ship10.cargohold))
|
||||
galaxy10.travel_to(savedata.galaxy10, savedata.planet10)
|
||||
|
||||
planet10.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy10 = galaxy10.number
|
||||
savedata.planet10 = planet10.number
|
||||
savedata.cash = ship10.cash
|
||||
savedata.max_cargo = ship10.Max_cargo
|
||||
savedata.fuel = ship10.fuel
|
||||
sys.memcopy(ship10.cargohold, &savedata.cargo0, len(ship10.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship10.fuel
|
||||
ship10.fuel = 255
|
||||
jump_to_system()
|
||||
ship10.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet10 = planet10.number
|
||||
ubyte x = planet10.x
|
||||
ubyte y = planet10.y
|
||||
if galaxy10.search_closest_planet10(input) {
|
||||
ubyte distance = planet10.distance(x, y)
|
||||
if distance <= ship10.fuel {
|
||||
galaxy10.init_market10_for_planet10()
|
||||
ship10.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet10.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy10.travel_to(galaxy10.number, current_planet10)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market10.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 market10.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market10.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util10.print_10s(price)
|
||||
if price > ship10.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship10.cash -= price
|
||||
ship10.cargohold[ci] += amount
|
||||
market10.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market10.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 ship10.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market10.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util10.print_10s(price)
|
||||
ship10.cash += price
|
||||
ship10.cargohold[ci] -= amount
|
||||
market10.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship10.Max_fuel - ship10.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship10.Fuel_cost
|
||||
if price > ship10.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship10.cash -= price
|
||||
ship10.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship10.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship10.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy10() {
|
||||
galaxy10.travel_to(galaxy10.number+1, planet10.number)
|
||||
planet10.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet10 = planet10.number
|
||||
if galaxy10.search_closest_planet10(input) {
|
||||
planet10.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy10.travel_to(galaxy10.number, current_planet10)
|
||||
} else {
|
||||
planet10.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy10.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market10() {
|
||||
market10.display()
|
||||
txt.print("\nFuel: ")
|
||||
util10.print_10s(ship10.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship10.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship10 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market10.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market10 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet10's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market10 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 = planet10.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet10.print_name_uppercase()
|
||||
txt.print(" trade market10:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util10.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util10.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship10.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util10.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy10 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy10
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy10num) {
|
||||
number = 1
|
||||
planet10.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy10num-1 {
|
||||
nextgalaxy10()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy10() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy10num, ubyte system) {
|
||||
init(galaxy10num)
|
||||
generate_next_planet10() ; always at least planet10 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet10()
|
||||
}
|
||||
planet10.name = make_current_planet10_name()
|
||||
init_market10_for_planet10()
|
||||
}
|
||||
|
||||
sub init_market10_for_planet10() {
|
||||
market10.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet10(uword nameptr) -> ubyte {
|
||||
ubyte x = planet10.x
|
||||
ubyte y = planet10.y
|
||||
ubyte current_planet10_num = planet10.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet10()
|
||||
planet10.name = make_current_planet10_name()
|
||||
if util10.prefix_matches(nameptr, planet10.name) {
|
||||
ubyte distance = planet10.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet10_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet10 = planet10.number
|
||||
ubyte px = planet10.x
|
||||
ubyte py = planet10.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet10()
|
||||
ubyte distance = planet10.distance(px, py)
|
||||
if distance <= ship10.Max_fuel {
|
||||
if distance <= ship10.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet10.name = make_current_planet10_name()
|
||||
planet10.display(true)
|
||||
txt.print(" (")
|
||||
util10.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet10)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet10() {
|
||||
determine_planet10_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet10_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet10_properties() {
|
||||
; create the planet10's characteristics
|
||||
planet10.number++
|
||||
planet10.x = msb(seed[1])
|
||||
planet10.y = msb(seed[0])
|
||||
planet10.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet10.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet10.govtype <= 1
|
||||
planet10.economy = (planet10.economy | 2)
|
||||
planet10.techlevel = (msb(seed[1]) & 3) + (planet10.economy ^ 7)
|
||||
planet10.techlevel += planet10.govtype >> 1
|
||||
if planet10.govtype & 1
|
||||
planet10.techlevel++
|
||||
planet10.population = 4 * planet10.techlevel + planet10.economy
|
||||
planet10.population += planet10.govtype + 1
|
||||
planet10.productivity = ((planet10.economy ^ 7) + 3) * (planet10.govtype + 4)
|
||||
planet10.productivity *= planet10.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet10.radius = mkword((seed2_msb & 15) + 11, planet10.x)
|
||||
planet10.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet10.species_is_alien {
|
||||
planet10.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet10.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet10.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet10.species_kind = (planet10.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
|
||||
}
|
||||
planet10.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet10.goatsoup_seed[1] = msb(seed[1])
|
||||
planet10.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet10.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy10 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy10 seed0=")
|
||||
txt.print_uwhex(galaxy10.seed[0], true)
|
||||
txt.print("\ngalaxy10 seed1=")
|
||||
txt.print_uwhex(galaxy10.seed[1], true)
|
||||
txt.print("\ngalaxy10 seed2=")
|
||||
txt.print_uwhex(galaxy10.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet10 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship10", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet10 \xB0", "The world \xB0", "This planet10", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet10", "world", "place", "little planet10", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy10, then increases by 1 for each generated planet10
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet10_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet10_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet10_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util10 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,994 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy2 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf2 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet2 in galaxy2 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy2.travel_to(1, numforLave)
|
||||
market2.init(0) ; Lave's market2 is seeded with 0
|
||||
ship2.init()
|
||||
planet2.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util2.print_10s(ship2.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market2 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader2.do_buy()
|
||||
's' -> trader2.do_sell()
|
||||
'f' -> trader2.do_fuel()
|
||||
'j' -> trader2.do_jump()
|
||||
't' -> trader2.do_teleport()
|
||||
'g' -> trader2.do_next_galaxy2()
|
||||
'i' -> trader2.do_info()
|
||||
'm' -> trader2.do_show_market2()
|
||||
'l' -> trader2.do_local()
|
||||
'c' -> trader2.do_cash()
|
||||
'h' -> trader2.do_hold()
|
||||
'<' -> trader2.do_load()
|
||||
'>' -> trader2.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader2 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy2
|
||||
ubyte planet2
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship2.cash = savedata.cash
|
||||
ship2.Max_cargo = savedata.max_cargo
|
||||
ship2.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship2.cargohold, len(ship2.cargohold))
|
||||
galaxy2.travel_to(savedata.galaxy2, savedata.planet2)
|
||||
|
||||
planet2.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy2 = galaxy2.number
|
||||
savedata.planet2 = planet2.number
|
||||
savedata.cash = ship2.cash
|
||||
savedata.max_cargo = ship2.Max_cargo
|
||||
savedata.fuel = ship2.fuel
|
||||
sys.memcopy(ship2.cargohold, &savedata.cargo0, len(ship2.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship2.fuel
|
||||
ship2.fuel = 255
|
||||
jump_to_system()
|
||||
ship2.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet2 = planet2.number
|
||||
ubyte x = planet2.x
|
||||
ubyte y = planet2.y
|
||||
if galaxy2.search_closest_planet2(input) {
|
||||
ubyte distance = planet2.distance(x, y)
|
||||
if distance <= ship2.fuel {
|
||||
galaxy2.init_market2_for_planet2()
|
||||
ship2.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet2.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy2.travel_to(galaxy2.number, current_planet2)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market2.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 market2.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market2.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util2.print_10s(price)
|
||||
if price > ship2.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship2.cash -= price
|
||||
ship2.cargohold[ci] += amount
|
||||
market2.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market2.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 ship2.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market2.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util2.print_10s(price)
|
||||
ship2.cash += price
|
||||
ship2.cargohold[ci] -= amount
|
||||
market2.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship2.Max_fuel - ship2.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship2.Fuel_cost
|
||||
if price > ship2.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship2.cash -= price
|
||||
ship2.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship2.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship2.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy2() {
|
||||
galaxy2.travel_to(galaxy2.number+1, planet2.number)
|
||||
planet2.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet2 = planet2.number
|
||||
if galaxy2.search_closest_planet2(input) {
|
||||
planet2.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy2.travel_to(galaxy2.number, current_planet2)
|
||||
} else {
|
||||
planet2.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy2.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market2() {
|
||||
market2.display()
|
||||
txt.print("\nFuel: ")
|
||||
util2.print_10s(ship2.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship2.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship2 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market2.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market2 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet2's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market2 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 = planet2.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet2.print_name_uppercase()
|
||||
txt.print(" trade market2:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util2.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util2.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship2.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util2.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy2 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy2
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy2num) {
|
||||
number = 1
|
||||
planet2.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy2num-1 {
|
||||
nextgalaxy2()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy2() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy2num, ubyte system) {
|
||||
init(galaxy2num)
|
||||
generate_next_planet2() ; always at least planet2 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet2()
|
||||
}
|
||||
planet2.name = make_current_planet2_name()
|
||||
init_market2_for_planet2()
|
||||
}
|
||||
|
||||
sub init_market2_for_planet2() {
|
||||
market2.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet2(uword nameptr) -> ubyte {
|
||||
ubyte x = planet2.x
|
||||
ubyte y = planet2.y
|
||||
ubyte current_planet2_num = planet2.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet2()
|
||||
planet2.name = make_current_planet2_name()
|
||||
if util2.prefix_matches(nameptr, planet2.name) {
|
||||
ubyte distance = planet2.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet2_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet2 = planet2.number
|
||||
ubyte px = planet2.x
|
||||
ubyte py = planet2.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet2()
|
||||
ubyte distance = planet2.distance(px, py)
|
||||
if distance <= ship2.Max_fuel {
|
||||
if distance <= ship2.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet2.name = make_current_planet2_name()
|
||||
planet2.display(true)
|
||||
txt.print(" (")
|
||||
util2.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet2)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet2() {
|
||||
determine_planet2_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet2_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet2_properties() {
|
||||
; create the planet2's characteristics
|
||||
planet2.number++
|
||||
planet2.x = msb(seed[1])
|
||||
planet2.y = msb(seed[0])
|
||||
planet2.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet2.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet2.govtype <= 1
|
||||
planet2.economy = (planet2.economy | 2)
|
||||
planet2.techlevel = (msb(seed[1]) & 3) + (planet2.economy ^ 7)
|
||||
planet2.techlevel += planet2.govtype >> 1
|
||||
if planet2.govtype & 1
|
||||
planet2.techlevel++
|
||||
planet2.population = 4 * planet2.techlevel + planet2.economy
|
||||
planet2.population += planet2.govtype + 1
|
||||
planet2.productivity = ((planet2.economy ^ 7) + 3) * (planet2.govtype + 4)
|
||||
planet2.productivity *= planet2.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet2.radius = mkword((seed2_msb & 15) + 11, planet2.x)
|
||||
planet2.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet2.species_is_alien {
|
||||
planet2.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet2.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet2.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet2.species_kind = (planet2.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
|
||||
}
|
||||
|
||||
planet2.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet2.goatsoup_seed[1] = msb(seed[1])
|
||||
planet2.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet2.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy2 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy2 seed0=")
|
||||
txt.print_uwhex(galaxy2.seed[0], true)
|
||||
txt.print("\ngalaxy2 seed1=")
|
||||
txt.print_uwhex(galaxy2.seed[1], true)
|
||||
txt.print("\ngalaxy2 seed2=")
|
||||
txt.print_uwhex(galaxy2.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet2 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship2", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet2 \xB0", "The world \xB0", "This planet2", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet2", "world", "place", "little planet2", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy2, then increases by 1 for each generated planet2
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet2_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet2_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet2_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util2 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,994 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy3 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf3 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet3 in galaxy3 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy3.travel_to(1, numforLave)
|
||||
market3.init(0) ; Lave's market3 is seeded with 0
|
||||
ship3.init()
|
||||
planet3.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util3.print_10s(ship3.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market3 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader3.do_buy()
|
||||
's' -> trader3.do_sell()
|
||||
'f' -> trader3.do_fuel()
|
||||
'j' -> trader3.do_jump()
|
||||
't' -> trader3.do_teleport()
|
||||
'g' -> trader3.do_next_galaxy3()
|
||||
'i' -> trader3.do_info()
|
||||
'm' -> trader3.do_show_market3()
|
||||
'l' -> trader3.do_local()
|
||||
'c' -> trader3.do_cash()
|
||||
'h' -> trader3.do_hold()
|
||||
'<' -> trader3.do_load()
|
||||
'>' -> trader3.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader3 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy3
|
||||
ubyte planet3
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship3.cash = savedata.cash
|
||||
ship3.Max_cargo = savedata.max_cargo
|
||||
ship3.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship3.cargohold, len(ship3.cargohold))
|
||||
galaxy3.travel_to(savedata.galaxy3, savedata.planet3)
|
||||
|
||||
planet3.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy3 = galaxy3.number
|
||||
savedata.planet3 = planet3.number
|
||||
savedata.cash = ship3.cash
|
||||
savedata.max_cargo = ship3.Max_cargo
|
||||
savedata.fuel = ship3.fuel
|
||||
sys.memcopy(ship3.cargohold, &savedata.cargo0, len(ship3.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship3.fuel
|
||||
ship3.fuel = 255
|
||||
jump_to_system()
|
||||
ship3.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet3 = planet3.number
|
||||
ubyte x = planet3.x
|
||||
ubyte y = planet3.y
|
||||
if galaxy3.search_closest_planet3(input) {
|
||||
ubyte distance = planet3.distance(x, y)
|
||||
if distance <= ship3.fuel {
|
||||
galaxy3.init_market3_for_planet3()
|
||||
ship3.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet3.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy3.travel_to(galaxy3.number, current_planet3)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market3.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 market3.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market3.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util3.print_10s(price)
|
||||
if price > ship3.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship3.cash -= price
|
||||
ship3.cargohold[ci] += amount
|
||||
market3.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market3.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 ship3.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market3.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util3.print_10s(price)
|
||||
ship3.cash += price
|
||||
ship3.cargohold[ci] -= amount
|
||||
market3.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship3.Max_fuel - ship3.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship3.Fuel_cost
|
||||
if price > ship3.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship3.cash -= price
|
||||
ship3.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship3.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship3.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy3() {
|
||||
galaxy3.travel_to(galaxy3.number+1, planet3.number)
|
||||
planet3.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet3 = planet3.number
|
||||
if galaxy3.search_closest_planet3(input) {
|
||||
planet3.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy3.travel_to(galaxy3.number, current_planet3)
|
||||
} else {
|
||||
planet3.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy3.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market3() {
|
||||
market3.display()
|
||||
txt.print("\nFuel: ")
|
||||
util3.print_10s(ship3.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship3.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship3 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market3.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market3 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet3's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market3 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 = planet3.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet3.print_name_uppercase()
|
||||
txt.print(" trade market3:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util3.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util3.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship3.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util3.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy3 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy3
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy3num) {
|
||||
number = 1
|
||||
planet3.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy3num-1 {
|
||||
nextgalaxy3()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy3() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy3num, ubyte system) {
|
||||
init(galaxy3num)
|
||||
generate_next_planet3() ; always at least planet3 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet3()
|
||||
}
|
||||
planet3.name = make_current_planet3_name()
|
||||
init_market3_for_planet3()
|
||||
}
|
||||
|
||||
sub init_market3_for_planet3() {
|
||||
market3.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet3(uword nameptr) -> ubyte {
|
||||
ubyte x = planet3.x
|
||||
ubyte y = planet3.y
|
||||
ubyte current_planet3_num = planet3.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet3()
|
||||
planet3.name = make_current_planet3_name()
|
||||
if util3.prefix_matches(nameptr, planet3.name) {
|
||||
ubyte distance = planet3.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet3_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet3 = planet3.number
|
||||
ubyte px = planet3.x
|
||||
ubyte py = planet3.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet3()
|
||||
ubyte distance = planet3.distance(px, py)
|
||||
if distance <= ship3.Max_fuel {
|
||||
if distance <= ship3.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet3.name = make_current_planet3_name()
|
||||
planet3.display(true)
|
||||
txt.print(" (")
|
||||
util3.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet3)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet3() {
|
||||
determine_planet3_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet3_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet3_properties() {
|
||||
; create the planet3's characteristics
|
||||
planet3.number++
|
||||
planet3.x = msb(seed[1])
|
||||
planet3.y = msb(seed[0])
|
||||
planet3.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet3.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet3.govtype <= 1
|
||||
planet3.economy = (planet3.economy | 2)
|
||||
planet3.techlevel = (msb(seed[1]) & 3) + (planet3.economy ^ 7)
|
||||
planet3.techlevel += planet3.govtype >> 1
|
||||
if planet3.govtype & 1
|
||||
planet3.techlevel++
|
||||
planet3.population = 4 * planet3.techlevel + planet3.economy
|
||||
planet3.population += planet3.govtype + 1
|
||||
planet3.productivity = ((planet3.economy ^ 7) + 3) * (planet3.govtype + 4)
|
||||
planet3.productivity *= planet3.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet3.radius = mkword((seed2_msb & 15) + 11, planet3.x)
|
||||
planet3.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet3.species_is_alien {
|
||||
planet3.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet3.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet3.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet3.species_kind = (planet3.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
|
||||
}
|
||||
|
||||
planet3.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet3.goatsoup_seed[1] = msb(seed[1])
|
||||
planet3.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet3.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy3 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy3 seed0=")
|
||||
txt.print_uwhex(galaxy3.seed[0], true)
|
||||
txt.print("\ngalaxy3 seed1=")
|
||||
txt.print_uwhex(galaxy3.seed[1], true)
|
||||
txt.print("\ngalaxy3 seed2=")
|
||||
txt.print_uwhex(galaxy3.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet3 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship3", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet3 \xB0", "The world \xB0", "This planet3", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet3", "world", "place", "little planet3", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy3, then increases by 1 for each generated planet3
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet3_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet3_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet3_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util3 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,994 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy4 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf4 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet4 in galaxy4 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy4.travel_to(1, numforLave)
|
||||
market4.init(0) ; Lave's market4 is seeded with 0
|
||||
ship4.init()
|
||||
planet4.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util4.print_10s(ship4.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market4 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader4.do_buy()
|
||||
's' -> trader4.do_sell()
|
||||
'f' -> trader4.do_fuel()
|
||||
'j' -> trader4.do_jump()
|
||||
't' -> trader4.do_teleport()
|
||||
'g' -> trader4.do_next_galaxy4()
|
||||
'i' -> trader4.do_info()
|
||||
'm' -> trader4.do_show_market4()
|
||||
'l' -> trader4.do_local()
|
||||
'c' -> trader4.do_cash()
|
||||
'h' -> trader4.do_hold()
|
||||
'<' -> trader4.do_load()
|
||||
'>' -> trader4.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader4 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy4
|
||||
ubyte planet4
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship4.cash = savedata.cash
|
||||
ship4.Max_cargo = savedata.max_cargo
|
||||
ship4.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship4.cargohold, len(ship4.cargohold))
|
||||
galaxy4.travel_to(savedata.galaxy4, savedata.planet4)
|
||||
|
||||
planet4.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy4 = galaxy4.number
|
||||
savedata.planet4 = planet4.number
|
||||
savedata.cash = ship4.cash
|
||||
savedata.max_cargo = ship4.Max_cargo
|
||||
savedata.fuel = ship4.fuel
|
||||
sys.memcopy(ship4.cargohold, &savedata.cargo0, len(ship4.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship4.fuel
|
||||
ship4.fuel = 255
|
||||
jump_to_system()
|
||||
ship4.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet4 = planet4.number
|
||||
ubyte x = planet4.x
|
||||
ubyte y = planet4.y
|
||||
if galaxy4.search_closest_planet4(input) {
|
||||
ubyte distance = planet4.distance(x, y)
|
||||
if distance <= ship4.fuel {
|
||||
galaxy4.init_market4_for_planet4()
|
||||
ship4.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet4.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy4.travel_to(galaxy4.number, current_planet4)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market4.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 market4.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market4.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util4.print_10s(price)
|
||||
if price > ship4.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship4.cash -= price
|
||||
ship4.cargohold[ci] += amount
|
||||
market4.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market4.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 ship4.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market4.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util4.print_10s(price)
|
||||
ship4.cash += price
|
||||
ship4.cargohold[ci] -= amount
|
||||
market4.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship4.Max_fuel - ship4.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship4.Fuel_cost
|
||||
if price > ship4.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship4.cash -= price
|
||||
ship4.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship4.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship4.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy4() {
|
||||
galaxy4.travel_to(galaxy4.number+1, planet4.number)
|
||||
planet4.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet4 = planet4.number
|
||||
if galaxy4.search_closest_planet4(input) {
|
||||
planet4.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy4.travel_to(galaxy4.number, current_planet4)
|
||||
} else {
|
||||
planet4.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy4.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market4() {
|
||||
market4.display()
|
||||
txt.print("\nFuel: ")
|
||||
util4.print_10s(ship4.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship4.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship4 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market4.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market4 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet4's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market4 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 = planet4.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet4.print_name_uppercase()
|
||||
txt.print(" trade market4:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util4.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util4.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship4.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util4.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy4 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy4
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy4num) {
|
||||
number = 1
|
||||
planet4.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy4num-1 {
|
||||
nextgalaxy4()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy4() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy4num, ubyte system) {
|
||||
init(galaxy4num)
|
||||
generate_next_planet4() ; always at least planet4 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet4()
|
||||
}
|
||||
planet4.name = make_current_planet4_name()
|
||||
init_market4_for_planet4()
|
||||
}
|
||||
|
||||
sub init_market4_for_planet4() {
|
||||
market4.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet4(uword nameptr) -> ubyte {
|
||||
ubyte x = planet4.x
|
||||
ubyte y = planet4.y
|
||||
ubyte current_planet4_num = planet4.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet4()
|
||||
planet4.name = make_current_planet4_name()
|
||||
if util4.prefix_matches(nameptr, planet4.name) {
|
||||
ubyte distance = planet4.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet4_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet4 = planet4.number
|
||||
ubyte px = planet4.x
|
||||
ubyte py = planet4.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet4()
|
||||
ubyte distance = planet4.distance(px, py)
|
||||
if distance <= ship4.Max_fuel {
|
||||
if distance <= ship4.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet4.name = make_current_planet4_name()
|
||||
planet4.display(true)
|
||||
txt.print(" (")
|
||||
util4.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet4)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet4() {
|
||||
determine_planet4_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet4_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet4_properties() {
|
||||
; create the planet4's characteristics
|
||||
planet4.number++
|
||||
planet4.x = msb(seed[1])
|
||||
planet4.y = msb(seed[0])
|
||||
planet4.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet4.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet4.govtype <= 1
|
||||
planet4.economy = (planet4.economy | 2)
|
||||
planet4.techlevel = (msb(seed[1]) & 3) + (planet4.economy ^ 7)
|
||||
planet4.techlevel += planet4.govtype >> 1
|
||||
if planet4.govtype & 1
|
||||
planet4.techlevel++
|
||||
planet4.population = 4 * planet4.techlevel + planet4.economy
|
||||
planet4.population += planet4.govtype + 1
|
||||
planet4.productivity = ((planet4.economy ^ 7) + 3) * (planet4.govtype + 4)
|
||||
planet4.productivity *= planet4.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet4.radius = mkword((seed2_msb & 15) + 11, planet4.x)
|
||||
planet4.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet4.species_is_alien {
|
||||
planet4.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet4.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet4.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet4.species_kind = (planet4.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
|
||||
}
|
||||
|
||||
planet4.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet4.goatsoup_seed[1] = msb(seed[1])
|
||||
planet4.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet4.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy4 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy4 seed0=")
|
||||
txt.print_uwhex(galaxy4.seed[0], true)
|
||||
txt.print("\ngalaxy4 seed1=")
|
||||
txt.print_uwhex(galaxy4.seed[1], true)
|
||||
txt.print("\ngalaxy4 seed2=")
|
||||
txt.print_uwhex(galaxy4.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet4 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship4", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet4 \xB0", "The world \xB0", "This planet4", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet4", "world", "place", "little planet4", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy4, then increases by 1 for each generated planet4
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet4_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet4_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet4_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util4 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,994 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy5 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf5 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet5 in galaxy5 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy5.travel_to(1, numforLave)
|
||||
market5.init(0) ; Lave's market5 is seeded with 0
|
||||
ship5.init()
|
||||
planet5.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util5.print_10s(ship5.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market5 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader5.do_buy()
|
||||
's' -> trader5.do_sell()
|
||||
'f' -> trader5.do_fuel()
|
||||
'j' -> trader5.do_jump()
|
||||
't' -> trader5.do_teleport()
|
||||
'g' -> trader5.do_next_galaxy5()
|
||||
'i' -> trader5.do_info()
|
||||
'm' -> trader5.do_show_market5()
|
||||
'l' -> trader5.do_local()
|
||||
'c' -> trader5.do_cash()
|
||||
'h' -> trader5.do_hold()
|
||||
'<' -> trader5.do_load()
|
||||
'>' -> trader5.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader5 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy5
|
||||
ubyte planet5
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship5.cash = savedata.cash
|
||||
ship5.Max_cargo = savedata.max_cargo
|
||||
ship5.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship5.cargohold, len(ship5.cargohold))
|
||||
galaxy5.travel_to(savedata.galaxy5, savedata.planet5)
|
||||
|
||||
planet5.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy5 = galaxy5.number
|
||||
savedata.planet5 = planet5.number
|
||||
savedata.cash = ship5.cash
|
||||
savedata.max_cargo = ship5.Max_cargo
|
||||
savedata.fuel = ship5.fuel
|
||||
sys.memcopy(ship5.cargohold, &savedata.cargo0, len(ship5.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship5.fuel
|
||||
ship5.fuel = 255
|
||||
jump_to_system()
|
||||
ship5.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet5 = planet5.number
|
||||
ubyte x = planet5.x
|
||||
ubyte y = planet5.y
|
||||
if galaxy5.search_closest_planet5(input) {
|
||||
ubyte distance = planet5.distance(x, y)
|
||||
if distance <= ship5.fuel {
|
||||
galaxy5.init_market5_for_planet5()
|
||||
ship5.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet5.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy5.travel_to(galaxy5.number, current_planet5)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market5.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 market5.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market5.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util5.print_10s(price)
|
||||
if price > ship5.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship5.cash -= price
|
||||
ship5.cargohold[ci] += amount
|
||||
market5.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market5.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 ship5.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market5.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util5.print_10s(price)
|
||||
ship5.cash += price
|
||||
ship5.cargohold[ci] -= amount
|
||||
market5.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship5.Max_fuel - ship5.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship5.Fuel_cost
|
||||
if price > ship5.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship5.cash -= price
|
||||
ship5.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship5.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship5.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy5() {
|
||||
galaxy5.travel_to(galaxy5.number+1, planet5.number)
|
||||
planet5.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet5 = planet5.number
|
||||
if galaxy5.search_closest_planet5(input) {
|
||||
planet5.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy5.travel_to(galaxy5.number, current_planet5)
|
||||
} else {
|
||||
planet5.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy5.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market5() {
|
||||
market5.display()
|
||||
txt.print("\nFuel: ")
|
||||
util5.print_10s(ship5.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship5.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship5 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market5.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market5 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet5's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market5 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 = planet5.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet5.print_name_uppercase()
|
||||
txt.print(" trade market5:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util5.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util5.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship5.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util5.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy5 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy5
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy5num) {
|
||||
number = 1
|
||||
planet5.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy5num-1 {
|
||||
nextgalaxy5()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy5() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy5num, ubyte system) {
|
||||
init(galaxy5num)
|
||||
generate_next_planet5() ; always at least planet5 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet5()
|
||||
}
|
||||
planet5.name = make_current_planet5_name()
|
||||
init_market5_for_planet5()
|
||||
}
|
||||
|
||||
sub init_market5_for_planet5() {
|
||||
market5.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet5(uword nameptr) -> ubyte {
|
||||
ubyte x = planet5.x
|
||||
ubyte y = planet5.y
|
||||
ubyte current_planet5_num = planet5.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet5()
|
||||
planet5.name = make_current_planet5_name()
|
||||
if util5.prefix_matches(nameptr, planet5.name) {
|
||||
ubyte distance = planet5.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet5_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet5 = planet5.number
|
||||
ubyte px = planet5.x
|
||||
ubyte py = planet5.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet5()
|
||||
ubyte distance = planet5.distance(px, py)
|
||||
if distance <= ship5.Max_fuel {
|
||||
if distance <= ship5.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet5.name = make_current_planet5_name()
|
||||
planet5.display(true)
|
||||
txt.print(" (")
|
||||
util5.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet5)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet5() {
|
||||
determine_planet5_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet5_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet5_properties() {
|
||||
; create the planet5's characteristics
|
||||
planet5.number++
|
||||
planet5.x = msb(seed[1])
|
||||
planet5.y = msb(seed[0])
|
||||
planet5.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet5.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet5.govtype <= 1
|
||||
planet5.economy = (planet5.economy | 2)
|
||||
planet5.techlevel = (msb(seed[1]) & 3) + (planet5.economy ^ 7)
|
||||
planet5.techlevel += planet5.govtype >> 1
|
||||
if planet5.govtype & 1
|
||||
planet5.techlevel++
|
||||
planet5.population = 4 * planet5.techlevel + planet5.economy
|
||||
planet5.population += planet5.govtype + 1
|
||||
planet5.productivity = ((planet5.economy ^ 7) + 3) * (planet5.govtype + 4)
|
||||
planet5.productivity *= planet5.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet5.radius = mkword((seed2_msb & 15) + 11, planet5.x)
|
||||
planet5.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet5.species_is_alien {
|
||||
planet5.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet5.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet5.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet5.species_kind = (planet5.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
|
||||
}
|
||||
|
||||
planet5.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet5.goatsoup_seed[1] = msb(seed[1])
|
||||
planet5.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet5.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy5 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy5 seed0=")
|
||||
txt.print_uwhex(galaxy5.seed[0], true)
|
||||
txt.print("\ngalaxy5 seed1=")
|
||||
txt.print_uwhex(galaxy5.seed[1], true)
|
||||
txt.print("\ngalaxy5 seed2=")
|
||||
txt.print_uwhex(galaxy5.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet5 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship5", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet5 \xB0", "The world \xB0", "This planet5", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet5", "world", "place", "little planet5", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy5, then increases by 1 for each generated planet5
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet5_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet5_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet5_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util5 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,994 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy6 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf6 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet6 in galaxy6 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy6.travel_to(1, numforLave)
|
||||
market6.init(0) ; Lave's market6 is seeded with 0
|
||||
ship6.init()
|
||||
planet6.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util6.print_10s(ship6.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market6 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader6.do_buy()
|
||||
's' -> trader6.do_sell()
|
||||
'f' -> trader6.do_fuel()
|
||||
'j' -> trader6.do_jump()
|
||||
't' -> trader6.do_teleport()
|
||||
'g' -> trader6.do_next_galaxy6()
|
||||
'i' -> trader6.do_info()
|
||||
'm' -> trader6.do_show_market6()
|
||||
'l' -> trader6.do_local()
|
||||
'c' -> trader6.do_cash()
|
||||
'h' -> trader6.do_hold()
|
||||
'<' -> trader6.do_load()
|
||||
'>' -> trader6.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader6 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy6
|
||||
ubyte planet6
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship6.cash = savedata.cash
|
||||
ship6.Max_cargo = savedata.max_cargo
|
||||
ship6.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship6.cargohold, len(ship6.cargohold))
|
||||
galaxy6.travel_to(savedata.galaxy6, savedata.planet6)
|
||||
|
||||
planet6.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy6 = galaxy6.number
|
||||
savedata.planet6 = planet6.number
|
||||
savedata.cash = ship6.cash
|
||||
savedata.max_cargo = ship6.Max_cargo
|
||||
savedata.fuel = ship6.fuel
|
||||
sys.memcopy(ship6.cargohold, &savedata.cargo0, len(ship6.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship6.fuel
|
||||
ship6.fuel = 255
|
||||
jump_to_system()
|
||||
ship6.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet6 = planet6.number
|
||||
ubyte x = planet6.x
|
||||
ubyte y = planet6.y
|
||||
if galaxy6.search_closest_planet6(input) {
|
||||
ubyte distance = planet6.distance(x, y)
|
||||
if distance <= ship6.fuel {
|
||||
galaxy6.init_market6_for_planet6()
|
||||
ship6.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet6.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy6.travel_to(galaxy6.number, current_planet6)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market6.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 market6.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market6.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util6.print_10s(price)
|
||||
if price > ship6.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship6.cash -= price
|
||||
ship6.cargohold[ci] += amount
|
||||
market6.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market6.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 ship6.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market6.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util6.print_10s(price)
|
||||
ship6.cash += price
|
||||
ship6.cargohold[ci] -= amount
|
||||
market6.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship6.Max_fuel - ship6.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship6.Fuel_cost
|
||||
if price > ship6.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship6.cash -= price
|
||||
ship6.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship6.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship6.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy6() {
|
||||
galaxy6.travel_to(galaxy6.number+1, planet6.number)
|
||||
planet6.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet6 = planet6.number
|
||||
if galaxy6.search_closest_planet6(input) {
|
||||
planet6.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy6.travel_to(galaxy6.number, current_planet6)
|
||||
} else {
|
||||
planet6.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy6.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market6() {
|
||||
market6.display()
|
||||
txt.print("\nFuel: ")
|
||||
util6.print_10s(ship6.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship6.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship6 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market6.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market6 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet6's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market6 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 = planet6.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet6.print_name_uppercase()
|
||||
txt.print(" trade market6:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util6.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util6.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship6.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util6.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy6 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy6
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy6num) {
|
||||
number = 1
|
||||
planet6.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy6num-1 {
|
||||
nextgalaxy6()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy6() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy6num, ubyte system) {
|
||||
init(galaxy6num)
|
||||
generate_next_planet6() ; always at least planet6 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet6()
|
||||
}
|
||||
planet6.name = make_current_planet6_name()
|
||||
init_market6_for_planet6()
|
||||
}
|
||||
|
||||
sub init_market6_for_planet6() {
|
||||
market6.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet6(uword nameptr) -> ubyte {
|
||||
ubyte x = planet6.x
|
||||
ubyte y = planet6.y
|
||||
ubyte current_planet6_num = planet6.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet6()
|
||||
planet6.name = make_current_planet6_name()
|
||||
if util6.prefix_matches(nameptr, planet6.name) {
|
||||
ubyte distance = planet6.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet6_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet6 = planet6.number
|
||||
ubyte px = planet6.x
|
||||
ubyte py = planet6.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet6()
|
||||
ubyte distance = planet6.distance(px, py)
|
||||
if distance <= ship6.Max_fuel {
|
||||
if distance <= ship6.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet6.name = make_current_planet6_name()
|
||||
planet6.display(true)
|
||||
txt.print(" (")
|
||||
util6.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet6)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet6() {
|
||||
determine_planet6_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet6_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet6_properties() {
|
||||
; create the planet6's characteristics
|
||||
planet6.number++
|
||||
planet6.x = msb(seed[1])
|
||||
planet6.y = msb(seed[0])
|
||||
planet6.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet6.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet6.govtype <= 1
|
||||
planet6.economy = (planet6.economy | 2)
|
||||
planet6.techlevel = (msb(seed[1]) & 3) + (planet6.economy ^ 7)
|
||||
planet6.techlevel += planet6.govtype >> 1
|
||||
if planet6.govtype & 1
|
||||
planet6.techlevel++
|
||||
planet6.population = 4 * planet6.techlevel + planet6.economy
|
||||
planet6.population += planet6.govtype + 1
|
||||
planet6.productivity = ((planet6.economy ^ 7) + 3) * (planet6.govtype + 4)
|
||||
planet6.productivity *= planet6.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet6.radius = mkword((seed2_msb & 15) + 11, planet6.x)
|
||||
planet6.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet6.species_is_alien {
|
||||
planet6.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet6.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet6.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet6.species_kind = (planet6.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
|
||||
}
|
||||
|
||||
planet6.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet6.goatsoup_seed[1] = msb(seed[1])
|
||||
planet6.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet6.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy6 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy6 seed0=")
|
||||
txt.print_uwhex(galaxy6.seed[0], true)
|
||||
txt.print("\ngalaxy6 seed1=")
|
||||
txt.print_uwhex(galaxy6.seed[1], true)
|
||||
txt.print("\ngalaxy6 seed2=")
|
||||
txt.print_uwhex(galaxy6.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet6 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship6", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet6 \xB0", "The world \xB0", "This planet6", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet6", "world", "place", "little planet6", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy6, then increases by 1 for each generated planet6
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet6_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet6_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet6_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util6 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,994 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy7 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf7 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet7 in galaxy7 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy7.travel_to(1, numforLave)
|
||||
market7.init(0) ; Lave's market7 is seeded with 0
|
||||
ship7.init()
|
||||
planet7.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util7.print_10s(ship7.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market7 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader7.do_buy()
|
||||
's' -> trader7.do_sell()
|
||||
'f' -> trader7.do_fuel()
|
||||
'j' -> trader7.do_jump()
|
||||
't' -> trader7.do_teleport()
|
||||
'g' -> trader7.do_next_galaxy7()
|
||||
'i' -> trader7.do_info()
|
||||
'm' -> trader7.do_show_market7()
|
||||
'l' -> trader7.do_local()
|
||||
'c' -> trader7.do_cash()
|
||||
'h' -> trader7.do_hold()
|
||||
'<' -> trader7.do_load()
|
||||
'>' -> trader7.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader7 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy7
|
||||
ubyte planet7
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship7.cash = savedata.cash
|
||||
ship7.Max_cargo = savedata.max_cargo
|
||||
ship7.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship7.cargohold, len(ship7.cargohold))
|
||||
galaxy7.travel_to(savedata.galaxy7, savedata.planet7)
|
||||
|
||||
planet7.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy7 = galaxy7.number
|
||||
savedata.planet7 = planet7.number
|
||||
savedata.cash = ship7.cash
|
||||
savedata.max_cargo = ship7.Max_cargo
|
||||
savedata.fuel = ship7.fuel
|
||||
sys.memcopy(ship7.cargohold, &savedata.cargo0, len(ship7.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship7.fuel
|
||||
ship7.fuel = 255
|
||||
jump_to_system()
|
||||
ship7.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet7 = planet7.number
|
||||
ubyte x = planet7.x
|
||||
ubyte y = planet7.y
|
||||
if galaxy7.search_closest_planet7(input) {
|
||||
ubyte distance = planet7.distance(x, y)
|
||||
if distance <= ship7.fuel {
|
||||
galaxy7.init_market7_for_planet7()
|
||||
ship7.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet7.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy7.travel_to(galaxy7.number, current_planet7)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market7.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 market7.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market7.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util7.print_10s(price)
|
||||
if price > ship7.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship7.cash -= price
|
||||
ship7.cargohold[ci] += amount
|
||||
market7.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market7.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 ship7.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market7.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util7.print_10s(price)
|
||||
ship7.cash += price
|
||||
ship7.cargohold[ci] -= amount
|
||||
market7.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship7.Max_fuel - ship7.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship7.Fuel_cost
|
||||
if price > ship7.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship7.cash -= price
|
||||
ship7.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship7.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship7.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy7() {
|
||||
galaxy7.travel_to(galaxy7.number+1, planet7.number)
|
||||
planet7.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet7 = planet7.number
|
||||
if galaxy7.search_closest_planet7(input) {
|
||||
planet7.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy7.travel_to(galaxy7.number, current_planet7)
|
||||
} else {
|
||||
planet7.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy7.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market7() {
|
||||
market7.display()
|
||||
txt.print("\nFuel: ")
|
||||
util7.print_10s(ship7.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship7.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship7 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market7.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market7 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet7's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market7 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 = planet7.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet7.print_name_uppercase()
|
||||
txt.print(" trade market7:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util7.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util7.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship7.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util7.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy7 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy7
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy7num) {
|
||||
number = 1
|
||||
planet7.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy7num-1 {
|
||||
nextgalaxy7()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy7() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy7num, ubyte system) {
|
||||
init(galaxy7num)
|
||||
generate_next_planet7() ; always at least planet7 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet7()
|
||||
}
|
||||
planet7.name = make_current_planet7_name()
|
||||
init_market7_for_planet7()
|
||||
}
|
||||
|
||||
sub init_market7_for_planet7() {
|
||||
market7.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet7(uword nameptr) -> ubyte {
|
||||
ubyte x = planet7.x
|
||||
ubyte y = planet7.y
|
||||
ubyte current_planet7_num = planet7.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet7()
|
||||
planet7.name = make_current_planet7_name()
|
||||
if util7.prefix_matches(nameptr, planet7.name) {
|
||||
ubyte distance = planet7.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet7_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet7 = planet7.number
|
||||
ubyte px = planet7.x
|
||||
ubyte py = planet7.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet7()
|
||||
ubyte distance = planet7.distance(px, py)
|
||||
if distance <= ship7.Max_fuel {
|
||||
if distance <= ship7.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet7.name = make_current_planet7_name()
|
||||
planet7.display(true)
|
||||
txt.print(" (")
|
||||
util7.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet7)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet7() {
|
||||
determine_planet7_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet7_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet7_properties() {
|
||||
; create the planet7's characteristics
|
||||
planet7.number++
|
||||
planet7.x = msb(seed[1])
|
||||
planet7.y = msb(seed[0])
|
||||
planet7.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet7.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet7.govtype <= 1
|
||||
planet7.economy = (planet7.economy | 2)
|
||||
planet7.techlevel = (msb(seed[1]) & 3) + (planet7.economy ^ 7)
|
||||
planet7.techlevel += planet7.govtype >> 1
|
||||
if planet7.govtype & 1
|
||||
planet7.techlevel++
|
||||
planet7.population = 4 * planet7.techlevel + planet7.economy
|
||||
planet7.population += planet7.govtype + 1
|
||||
planet7.productivity = ((planet7.economy ^ 7) + 3) * (planet7.govtype + 4)
|
||||
planet7.productivity *= planet7.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet7.radius = mkword((seed2_msb & 15) + 11, planet7.x)
|
||||
planet7.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet7.species_is_alien {
|
||||
planet7.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet7.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet7.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet7.species_kind = (planet7.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
|
||||
}
|
||||
|
||||
planet7.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet7.goatsoup_seed[1] = msb(seed[1])
|
||||
planet7.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet7.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy7 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy7 seed0=")
|
||||
txt.print_uwhex(galaxy7.seed[0], true)
|
||||
txt.print("\ngalaxy7 seed1=")
|
||||
txt.print_uwhex(galaxy7.seed[1], true)
|
||||
txt.print("\ngalaxy7 seed2=")
|
||||
txt.print_uwhex(galaxy7.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet7 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship7", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet7 \xB0", "The world \xB0", "This planet7", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet7", "world", "place", "little planet7", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy7, then increases by 1 for each generated planet7
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet7_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet7_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet7_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util7 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,994 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy8 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf8 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet8 in galaxy8 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy8.travel_to(1, numforLave)
|
||||
market8.init(0) ; Lave's market8 is seeded with 0
|
||||
ship8.init()
|
||||
planet8.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util8.print_10s(ship8.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market8 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader8.do_buy()
|
||||
's' -> trader8.do_sell()
|
||||
'f' -> trader8.do_fuel()
|
||||
'j' -> trader8.do_jump()
|
||||
't' -> trader8.do_teleport()
|
||||
'g' -> trader8.do_next_galaxy8()
|
||||
'i' -> trader8.do_info()
|
||||
'm' -> trader8.do_show_market8()
|
||||
'l' -> trader8.do_local()
|
||||
'c' -> trader8.do_cash()
|
||||
'h' -> trader8.do_hold()
|
||||
'<' -> trader8.do_load()
|
||||
'>' -> trader8.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader8 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy8
|
||||
ubyte planet8
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship8.cash = savedata.cash
|
||||
ship8.Max_cargo = savedata.max_cargo
|
||||
ship8.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship8.cargohold, len(ship8.cargohold))
|
||||
galaxy8.travel_to(savedata.galaxy8, savedata.planet8)
|
||||
|
||||
planet8.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy8 = galaxy8.number
|
||||
savedata.planet8 = planet8.number
|
||||
savedata.cash = ship8.cash
|
||||
savedata.max_cargo = ship8.Max_cargo
|
||||
savedata.fuel = ship8.fuel
|
||||
sys.memcopy(ship8.cargohold, &savedata.cargo0, len(ship8.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship8.fuel
|
||||
ship8.fuel = 255
|
||||
jump_to_system()
|
||||
ship8.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet8 = planet8.number
|
||||
ubyte x = planet8.x
|
||||
ubyte y = planet8.y
|
||||
if galaxy8.search_closest_planet8(input) {
|
||||
ubyte distance = planet8.distance(x, y)
|
||||
if distance <= ship8.fuel {
|
||||
galaxy8.init_market8_for_planet8()
|
||||
ship8.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet8.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy8.travel_to(galaxy8.number, current_planet8)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market8.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 market8.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market8.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util8.print_10s(price)
|
||||
if price > ship8.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship8.cash -= price
|
||||
ship8.cargohold[ci] += amount
|
||||
market8.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market8.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 ship8.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market8.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util8.print_10s(price)
|
||||
ship8.cash += price
|
||||
ship8.cargohold[ci] -= amount
|
||||
market8.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship8.Max_fuel - ship8.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship8.Fuel_cost
|
||||
if price > ship8.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship8.cash -= price
|
||||
ship8.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship8.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship8.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy8() {
|
||||
galaxy8.travel_to(galaxy8.number+1, planet8.number)
|
||||
planet8.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet8 = planet8.number
|
||||
if galaxy8.search_closest_planet8(input) {
|
||||
planet8.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy8.travel_to(galaxy8.number, current_planet8)
|
||||
} else {
|
||||
planet8.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy8.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market8() {
|
||||
market8.display()
|
||||
txt.print("\nFuel: ")
|
||||
util8.print_10s(ship8.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship8.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship8 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market8.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market8 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet8's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market8 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 = planet8.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet8.print_name_uppercase()
|
||||
txt.print(" trade market8:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util8.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util8.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship8.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util8.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy8 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy8
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy8num) {
|
||||
number = 1
|
||||
planet8.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy8num-1 {
|
||||
nextgalaxy8()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy8() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy8num, ubyte system) {
|
||||
init(galaxy8num)
|
||||
generate_next_planet8() ; always at least planet8 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet8()
|
||||
}
|
||||
planet8.name = make_current_planet8_name()
|
||||
init_market8_for_planet8()
|
||||
}
|
||||
|
||||
sub init_market8_for_planet8() {
|
||||
market8.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet8(uword nameptr) -> ubyte {
|
||||
ubyte x = planet8.x
|
||||
ubyte y = planet8.y
|
||||
ubyte current_planet8_num = planet8.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet8()
|
||||
planet8.name = make_current_planet8_name()
|
||||
if util8.prefix_matches(nameptr, planet8.name) {
|
||||
ubyte distance = planet8.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet8_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet8 = planet8.number
|
||||
ubyte px = planet8.x
|
||||
ubyte py = planet8.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet8()
|
||||
ubyte distance = planet8.distance(px, py)
|
||||
if distance <= ship8.Max_fuel {
|
||||
if distance <= ship8.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet8.name = make_current_planet8_name()
|
||||
planet8.display(true)
|
||||
txt.print(" (")
|
||||
util8.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet8)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet8() {
|
||||
determine_planet8_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet8_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet8_properties() {
|
||||
; create the planet8's characteristics
|
||||
planet8.number++
|
||||
planet8.x = msb(seed[1])
|
||||
planet8.y = msb(seed[0])
|
||||
planet8.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet8.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet8.govtype <= 1
|
||||
planet8.economy = (planet8.economy | 2)
|
||||
planet8.techlevel = (msb(seed[1]) & 3) + (planet8.economy ^ 7)
|
||||
planet8.techlevel += planet8.govtype >> 1
|
||||
if planet8.govtype & 1
|
||||
planet8.techlevel++
|
||||
planet8.population = 4 * planet8.techlevel + planet8.economy
|
||||
planet8.population += planet8.govtype + 1
|
||||
planet8.productivity = ((planet8.economy ^ 7) + 3) * (planet8.govtype + 4)
|
||||
planet8.productivity *= planet8.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet8.radius = mkword((seed2_msb & 15) + 11, planet8.x)
|
||||
planet8.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet8.species_is_alien {
|
||||
planet8.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet8.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet8.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet8.species_kind = (planet8.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
|
||||
}
|
||||
|
||||
planet8.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet8.goatsoup_seed[1] = msb(seed[1])
|
||||
planet8.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet8.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy8 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy8 seed0=")
|
||||
txt.print_uwhex(galaxy8.seed[0], true)
|
||||
txt.print("\ngalaxy8 seed1=")
|
||||
txt.print_uwhex(galaxy8.seed[1], true)
|
||||
txt.print("\ngalaxy8 seed2=")
|
||||
txt.print_uwhex(galaxy8.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet8 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship8", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet8 \xB0", "The world \xB0", "This planet8", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet8", "world", "place", "little planet8", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy8, then increases by 1 for each generated planet8
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet8_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet8_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet8_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util8 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,993 +0,0 @@
|
|||
%import textio
|
||||
%import conv
|
||||
%import diskio
|
||||
%import string
|
||||
%import test_stack
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
; Prog8 adaptation of the Text-Elite galaxy9 system trading simulation engine.
|
||||
; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
||||
perf9 {
|
||||
|
||||
const ubyte numforLave = 7 ; Lave is 7th generated planet9 in galaxy9 one
|
||||
const ubyte numforZaonce = 129
|
||||
const ubyte numforDiso = 147
|
||||
const ubyte numforRiedquat = 46
|
||||
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
txt.print("\u000c\n --- TextElite v1.1 ---\n")
|
||||
|
||||
galaxy9.travel_to(1, numforLave)
|
||||
market9.init(0) ; Lave's market9 is seeded with 0
|
||||
ship9.init()
|
||||
planet9.display(false)
|
||||
|
||||
repeat {
|
||||
; test_stack.test()
|
||||
|
||||
str input = "????????"
|
||||
txt.print("\nCash: ")
|
||||
util9.print_10s(ship9.cash)
|
||||
txt.print("\nCommand (?=help): ")
|
||||
ubyte num_chars = txt.input_chars(input)
|
||||
txt.nl()
|
||||
if num_chars {
|
||||
when input[0] {
|
||||
'?' -> {
|
||||
txt.print("\nCommands are:\n"+
|
||||
"buy jump info cash >=save\n"+
|
||||
"sell teleport market9 hold <=load\n"+
|
||||
"fuel galhyp local quit\n")
|
||||
}
|
||||
'q' -> break
|
||||
'b' -> trader9.do_buy()
|
||||
's' -> trader9.do_sell()
|
||||
'f' -> trader9.do_fuel()
|
||||
'j' -> trader9.do_jump()
|
||||
't' -> trader9.do_teleport()
|
||||
'g' -> trader9.do_next_galaxy9()
|
||||
'i' -> trader9.do_info()
|
||||
'm' -> trader9.do_show_market9()
|
||||
'l' -> trader9.do_local()
|
||||
'c' -> trader9.do_cash()
|
||||
'h' -> trader9.do_hold()
|
||||
'<' -> trader9.do_load()
|
||||
'>' -> trader9.do_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trader9 {
|
||||
str Savegame = "↑commander.save"
|
||||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
ubyte galaxy9
|
||||
ubyte planet9
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
if diskio.load(8, Savegame, &savedata) {
|
||||
txt.print("ok\n")
|
||||
} else {
|
||||
txt.print("\ni/o error: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
return
|
||||
}
|
||||
|
||||
ship9.cash = savedata.cash
|
||||
ship9.Max_cargo = savedata.max_cargo
|
||||
ship9.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship9.cargohold, len(ship9.cargohold))
|
||||
galaxy9.travel_to(savedata.galaxy9, savedata.planet9)
|
||||
|
||||
planet9.display(false)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
savedata.galaxy9 = galaxy9.number
|
||||
savedata.planet9 = planet9.number
|
||||
savedata.cash = ship9.cash
|
||||
savedata.max_cargo = ship9.Max_cargo
|
||||
savedata.fuel = ship9.fuel
|
||||
sys.memcopy(ship9.cargohold, &savedata.cargo0, len(ship9.cargohold))
|
||||
|
||||
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: ")
|
||||
txt.print(diskio.status(8))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub do_jump() {
|
||||
txt.print("\nJump to what system? ")
|
||||
jump_to_system()
|
||||
}
|
||||
|
||||
sub do_teleport() {
|
||||
txt.print("\nCheat! Teleport to what system? ")
|
||||
ubyte fuel = ship9.fuel
|
||||
ship9.fuel = 255
|
||||
jump_to_system()
|
||||
ship9.fuel = fuel
|
||||
}
|
||||
|
||||
sub jump_to_system() {
|
||||
void txt.input_chars(input)
|
||||
ubyte current_planet9 = planet9.number
|
||||
ubyte x = planet9.x
|
||||
ubyte y = planet9.y
|
||||
if galaxy9.search_closest_planet9(input) {
|
||||
ubyte distance = planet9.distance(x, y)
|
||||
if distance <= ship9.fuel {
|
||||
galaxy9.init_market9_for_planet9()
|
||||
ship9.fuel -= distance
|
||||
txt.print("\n\nHyperspace jump! Arrived at:\n")
|
||||
planet9.display(true)
|
||||
return
|
||||
}
|
||||
txt.print("Insufficient fuel\n")
|
||||
} else {
|
||||
txt.print(" Not found!\n")
|
||||
}
|
||||
galaxy9.travel_to(galaxy9.number, current_planet9)
|
||||
}
|
||||
|
||||
sub do_buy() {
|
||||
txt.print("\nBuy what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market9.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 market9.current_quantity[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market9.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util9.print_10s(price)
|
||||
if price > ship9.cash {
|
||||
txt.print(" Not enough cash!\n")
|
||||
} else {
|
||||
ship9.cash -= price
|
||||
ship9.cargohold[ci] += amount
|
||||
market9.current_quantity[ci] -= amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_sell() {
|
||||
txt.print("\nSell what commodity? ")
|
||||
str commodity = "???????????????"
|
||||
void txt.input_chars(commodity)
|
||||
ubyte ci = market9.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 ship9.cargohold[ci] < amount {
|
||||
txt.print(" Insufficient supply!\n")
|
||||
} else {
|
||||
uword price = market9.current_price[ci] * amount
|
||||
txt.print(" Total price: ")
|
||||
util9.print_10s(price)
|
||||
ship9.cash += price
|
||||
ship9.cargohold[ci] -= amount
|
||||
market9.current_quantity[ci] += amount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_fuel() {
|
||||
txt.print("\nBuy fuel. Amount? ")
|
||||
void txt.input_chars(input)
|
||||
ubyte buy_fuel = 10*conv.str2ubyte(input)
|
||||
ubyte max_fuel = ship9.Max_fuel - ship9.fuel
|
||||
if buy_fuel > max_fuel
|
||||
buy_fuel = max_fuel
|
||||
uword price = buy_fuel as uword * ship9.Fuel_cost
|
||||
if price > ship9.cash {
|
||||
txt.print("Not enough cash!\n")
|
||||
} else {
|
||||
ship9.cash -= price
|
||||
ship9.fuel += buy_fuel
|
||||
}
|
||||
}
|
||||
|
||||
sub do_cash() {
|
||||
txt.print("\nCheat! Set cash amount: ")
|
||||
void txt.input_chars(input)
|
||||
ship9.cash = conv.str2uword(input)
|
||||
}
|
||||
|
||||
sub do_hold() {
|
||||
txt.print("\nCheat! Set cargohold size: ")
|
||||
void txt.input_chars(input)
|
||||
ship9.Max_cargo = conv.str2ubyte(input)
|
||||
}
|
||||
|
||||
sub do_next_galaxy9() {
|
||||
galaxy9.travel_to(galaxy9.number+1, planet9.number)
|
||||
planet9.display(false)
|
||||
}
|
||||
|
||||
sub do_info() {
|
||||
txt.print("\nSystem name (empty=current): ")
|
||||
num_chars = txt.input_chars(input)
|
||||
if num_chars {
|
||||
ubyte current_planet9 = planet9.number
|
||||
if galaxy9.search_closest_planet9(input) {
|
||||
planet9.display(false)
|
||||
} else {
|
||||
txt.print(" Not found!")
|
||||
}
|
||||
galaxy9.travel_to(galaxy9.number, current_planet9)
|
||||
} else {
|
||||
planet9.display(false)
|
||||
}
|
||||
}
|
||||
|
||||
sub do_local() {
|
||||
galaxy9.local_area()
|
||||
}
|
||||
|
||||
sub do_show_market9() {
|
||||
market9.display()
|
||||
txt.print("\nFuel: ")
|
||||
util9.print_10s(ship9.fuel)
|
||||
txt.print(" Cargohold space: ")
|
||||
txt.print_ub(ship9.cargo_free())
|
||||
txt.print("t\n")
|
||||
}
|
||||
}
|
||||
|
||||
ship9 {
|
||||
const ubyte Max_fuel = 70
|
||||
const ubyte Fuel_cost = 2
|
||||
ubyte Max_cargo = 20
|
||||
|
||||
ubyte fuel = Max_fuel
|
||||
uword cash = 1000 ; actually has to be 4 bytes for the ultra rich....
|
||||
ubyte[17] cargohold = 0
|
||||
|
||||
sub init() {
|
||||
sys.memset(cargohold, len(cargohold), 0)
|
||||
}
|
||||
|
||||
sub cargo_free() -> ubyte {
|
||||
ubyte ci
|
||||
ubyte total = 0
|
||||
for ci in 0 to len(cargohold)-1 {
|
||||
if market9.units[ci]==0 ; tonnes only
|
||||
total += cargohold[ci]
|
||||
}
|
||||
return Max_cargo - total
|
||||
}
|
||||
}
|
||||
|
||||
market9 {
|
||||
ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35]
|
||||
byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F]
|
||||
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
|
||||
uword[17] current_price = 0
|
||||
|
||||
sub init(ubyte fluct) {
|
||||
; Prices and availabilities are influenced by the planet9's economy type
|
||||
; (0-7) and a random "fluctuation" byte that was kept within the saved
|
||||
; commander position to keep the market9 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 = planet9.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
|
||||
}
|
||||
|
||||
sub display() {
|
||||
ubyte ci
|
||||
txt.nl()
|
||||
planet9.print_name_uppercase()
|
||||
txt.print(" trade market9:\n COMMODITY / PRICE / AVAIL / IN HOLD\n")
|
||||
for ci in 0 to len(names)-1 {
|
||||
util9.print_right(13, names[ci])
|
||||
txt.print(" ")
|
||||
util9.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')
|
||||
}
|
||||
txt.print(" ")
|
||||
txt.print_ub(ship9.cargohold[ci])
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub match(uword nameptr) -> ubyte {
|
||||
ubyte ci
|
||||
for ci in 0 to len(names)-1 {
|
||||
if util9.prefix_matches(nameptr, names[ci])
|
||||
return ci
|
||||
}
|
||||
return 255
|
||||
}
|
||||
}
|
||||
|
||||
galaxy9 {
|
||||
const uword GALSIZE = 256
|
||||
const uword base0 = $5A4A ; seeds for the first galaxy9
|
||||
const uword base1 = $0248
|
||||
const uword base2 = $B753
|
||||
|
||||
str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"
|
||||
|
||||
ubyte number
|
||||
|
||||
uword[3] seed
|
||||
|
||||
sub init(ubyte galaxy9num) {
|
||||
number = 1
|
||||
planet9.number = 255
|
||||
seed[0] = base0
|
||||
seed[1] = base1
|
||||
seed[2] = base2
|
||||
repeat galaxy9num-1 {
|
||||
nextgalaxy9()
|
||||
}
|
||||
}
|
||||
|
||||
sub nextgalaxy9() {
|
||||
seed[0] = twist(seed[0])
|
||||
seed[1] = twist(seed[1])
|
||||
seed[2] = twist(seed[2])
|
||||
number++
|
||||
if number==9
|
||||
number = 1
|
||||
}
|
||||
|
||||
sub travel_to(ubyte galaxy9num, ubyte system) {
|
||||
init(galaxy9num)
|
||||
generate_next_planet9() ; always at least planet9 0 (separate to avoid repeat ubyte overflow)
|
||||
repeat system {
|
||||
generate_next_planet9()
|
||||
}
|
||||
planet9.name = make_current_planet9_name()
|
||||
init_market9_for_planet9()
|
||||
}
|
||||
|
||||
sub init_market9_for_planet9() {
|
||||
market9.init(lsb(seed[0])+msb(seed[2]))
|
||||
}
|
||||
|
||||
sub search_closest_planet9(uword nameptr) -> ubyte {
|
||||
ubyte x = planet9.x
|
||||
ubyte y = planet9.y
|
||||
ubyte current_planet9_num = planet9.number
|
||||
|
||||
init(number)
|
||||
ubyte found = false
|
||||
ubyte current_closest_pi
|
||||
ubyte current_distance = 127
|
||||
ubyte pi
|
||||
for pi in 0 to 255 {
|
||||
generate_next_planet9()
|
||||
planet9.name = make_current_planet9_name()
|
||||
if util9.prefix_matches(nameptr, planet9.name) {
|
||||
ubyte distance = planet9.distance(x, y)
|
||||
if distance < current_distance {
|
||||
current_distance = distance
|
||||
current_closest_pi = pi
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found
|
||||
travel_to(number, current_closest_pi)
|
||||
else
|
||||
travel_to(number, current_planet9_num)
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
sub local_area() {
|
||||
ubyte current_planet9 = planet9.number
|
||||
ubyte px = planet9.x
|
||||
ubyte py = planet9.y
|
||||
ubyte pn = 0
|
||||
|
||||
init(number)
|
||||
txt.print("\nGalaxy #")
|
||||
txt.print_ub(number)
|
||||
txt.print(" - systems in vicinity:\n")
|
||||
do {
|
||||
generate_next_planet9()
|
||||
ubyte distance = planet9.distance(px, py)
|
||||
if distance <= ship9.Max_fuel {
|
||||
if distance <= ship9.fuel
|
||||
txt.chrout('*')
|
||||
else
|
||||
txt.chrout('-')
|
||||
txt.spc()
|
||||
planet9.name = make_current_planet9_name()
|
||||
planet9.display(true)
|
||||
txt.print(" (")
|
||||
util9.print_10s(distance)
|
||||
txt.print(" LY)\n")
|
||||
}
|
||||
pn++
|
||||
} until pn==0
|
||||
|
||||
travel_to(number, current_planet9)
|
||||
}
|
||||
|
||||
ubyte pn_pair1
|
||||
ubyte pn_pair2
|
||||
ubyte pn_pair3
|
||||
ubyte pn_pair4
|
||||
ubyte longname
|
||||
|
||||
sub generate_next_planet9() {
|
||||
determine_planet9_properties()
|
||||
longname = lsb(seed[0]) & 64
|
||||
|
||||
; Always four iterations of random number
|
||||
pn_pair1 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair2 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair3 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
pn_pair4 = (msb(seed[2]) & 31) * 2
|
||||
tweakseed()
|
||||
}
|
||||
|
||||
sub make_current_planet9_name() -> str {
|
||||
ubyte ni = 0
|
||||
str name = " " ; max 8
|
||||
|
||||
if pn_pairs[pn_pair1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair1+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair1+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair2+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair2+1]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair3+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair3+1]
|
||||
ni++
|
||||
}
|
||||
|
||||
if longname {
|
||||
if pn_pairs[pn_pair4] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4]
|
||||
ni++
|
||||
}
|
||||
if pn_pairs[pn_pair4+1] != '.' {
|
||||
name[ni] = pn_pairs[pn_pair4+1]
|
||||
ni++
|
||||
}
|
||||
}
|
||||
|
||||
name[ni] = 0
|
||||
return name
|
||||
}
|
||||
|
||||
sub determine_planet9_properties() {
|
||||
; create the planet9's characteristics
|
||||
planet9.number++
|
||||
planet9.x = msb(seed[1])
|
||||
planet9.y = msb(seed[0])
|
||||
planet9.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1
|
||||
planet9.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0
|
||||
if planet9.govtype <= 1
|
||||
planet9.economy = (planet9.economy | 2)
|
||||
planet9.techlevel = (msb(seed[1]) & 3) + (planet9.economy ^ 7)
|
||||
planet9.techlevel += planet9.govtype >> 1
|
||||
if planet9.govtype & 1
|
||||
planet9.techlevel++
|
||||
planet9.population = 4 * planet9.techlevel + planet9.economy
|
||||
planet9.population += planet9.govtype + 1
|
||||
planet9.productivity = ((planet9.economy ^ 7) + 3) * (planet9.govtype + 4)
|
||||
planet9.productivity *= planet9.population * 8
|
||||
ubyte seed2_msb = msb(seed[2])
|
||||
planet9.radius = mkword((seed2_msb & 15) + 11, planet9.x)
|
||||
planet9.species_is_alien = lsb(seed[2]) & 128 ; bit 7 of w2_lo
|
||||
if planet9.species_is_alien {
|
||||
planet9.species_size = (seed2_msb >> 2) & 7 ; bits 2-4 of w2_hi
|
||||
planet9.species_color = seed2_msb >> 5 ; bits 5-7 of w2_hi
|
||||
planet9.species_look = (seed2_msb ^ msb(seed[1])) & 7 ;bits 0-2 of (w0_hi EOR w1_hi)
|
||||
planet9.species_kind = (planet9.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
|
||||
}
|
||||
planet9.goatsoup_seed[0] = lsb(seed[1])
|
||||
planet9.goatsoup_seed[1] = msb(seed[1])
|
||||
planet9.goatsoup_seed[2] = lsb(seed[2])
|
||||
planet9.goatsoup_seed[3] = seed2_msb
|
||||
}
|
||||
|
||||
sub tweakseed() {
|
||||
uword temp = seed[0] + seed[1] + seed[2]
|
||||
seed[0] = seed[1]
|
||||
seed[1] = seed[2]
|
||||
seed[2] = temp
|
||||
}
|
||||
|
||||
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("\ngalaxy9 #")
|
||||
txt.print_ub(number)
|
||||
txt.print("\ngalaxy9 seed0=")
|
||||
txt.print_uwhex(galaxy9.seed[0], true)
|
||||
txt.print("\ngalaxy9 seed1=")
|
||||
txt.print_uwhex(galaxy9.seed[1], true)
|
||||
txt.print("\ngalaxy9 seed2=")
|
||||
txt.print_uwhex(galaxy9.seed[2], true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
planet9 {
|
||||
%option force_output
|
||||
|
||||
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"]
|
||||
str[] govnames = ["Anarchy", "Feudal", "Multi-gov", "Dictatorship9", "Communist", "Confederacy", "Democracy", "Corporate State"]
|
||||
str[] econnames = ["Rich Industrial", "Average Industrial", "Poor Industrial", "Mainly Industrial",
|
||||
"Mainly Agricultural", "Rich Agricultural", "Average Agricultural", "Poor Agricultural"]
|
||||
|
||||
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"]
|
||||
str[] words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"]
|
||||
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 planet9 \xB0", "The world \xB0", "This planet9", "This world"]
|
||||
str[] words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"]
|
||||
str[] words91 = ["planet9", "world", "place", "little planet9", "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"]
|
||||
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"]
|
||||
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"]
|
||||
str[] wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"]
|
||||
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"
|
||||
|
||||
ubyte[4] goatsoup_rnd = [0, 0, 0, 0]
|
||||
ubyte[4] goatsoup_seed = [0, 0, 0, 0]
|
||||
|
||||
str name = " " ; 8 max
|
||||
ubyte number ; starts at 0 in new galaxy9, then increases by 1 for each generated planet9
|
||||
ubyte x
|
||||
ubyte y
|
||||
ubyte economy
|
||||
ubyte govtype
|
||||
ubyte techlevel
|
||||
ubyte population
|
||||
uword productivity
|
||||
uword radius
|
||||
ubyte species_is_alien ; otherwise "Human Colonials"
|
||||
ubyte species_size
|
||||
ubyte species_color
|
||||
ubyte species_look
|
||||
ubyte species_kind
|
||||
|
||||
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
|
||||
for ii in 0 to goatsoup_rnd_number() & 3 {
|
||||
ubyte x = goatsoup_rnd_number() & $3e
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
x++
|
||||
if pairs0[x] != '.' {
|
||||
name[nx] = pairs0[x]
|
||||
nx++
|
||||
}
|
||||
}
|
||||
name[nx] = 0
|
||||
name[0] |= 32 ; uppercase first letter
|
||||
return name
|
||||
}
|
||||
|
||||
sub goatsoup_rnd_number() -> ubyte {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
sub soup() -> str {
|
||||
str planet9_result = " " * 160
|
||||
uword[6] source_stack
|
||||
ubyte stack_ptr = 0
|
||||
str start_source = "\x8F is \x97."
|
||||
uword source_ptr = &start_source
|
||||
uword result_ptr = &planet9_result
|
||||
|
||||
reset_rnd()
|
||||
recursive_soup()
|
||||
return planet9_result
|
||||
|
||||
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 {
|
||||
ubyte rnr = goatsoup_rnd_number()
|
||||
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
|
||||
stack_ptr--
|
||||
source_ptr = source_stack[stack_ptr]
|
||||
} else {
|
||||
if c == $b0 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
concat_string(&name + 1)
|
||||
}
|
||||
else if c == $b1 {
|
||||
@(result_ptr) = name[0] | 32
|
||||
result_ptr++
|
||||
ubyte ni
|
||||
for ni in 1 to len(name) {
|
||||
ubyte cc = name[ni]
|
||||
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 {
|
||||
concat_string(random_name())
|
||||
}
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub concat_string(uword str_ptr) {
|
||||
repeat {
|
||||
ubyte c = @(str_ptr)
|
||||
if c==0
|
||||
break
|
||||
else {
|
||||
@(result_ptr) = c
|
||||
str_ptr++
|
||||
result_ptr++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub display(ubyte compressed) {
|
||||
if compressed {
|
||||
print_name_uppercase()
|
||||
txt.print(" TL:")
|
||||
txt.print_ub(techlevel+1)
|
||||
txt.spc()
|
||||
txt.print(econnames[economy])
|
||||
txt.spc()
|
||||
txt.print(govnames[govtype])
|
||||
} else {
|
||||
txt.print("\n\nSystem: ")
|
||||
print_name_uppercase()
|
||||
txt.print("\nPosition: ")
|
||||
txt.print_ub(x)
|
||||
txt.chrout('\'')
|
||||
txt.print_ub(y)
|
||||
txt.spc()
|
||||
txt.chrout('#')
|
||||
txt.print_ub(number)
|
||||
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)
|
||||
txt.print("\nPopulation: ")
|
||||
txt.print_ub(population >> 3)
|
||||
txt.print(" Billion\nSpecies: ")
|
||||
if species_is_alien {
|
||||
if species_size < len(species_sizes) {
|
||||
txt.print(species_sizes[species_size])
|
||||
txt.spc()
|
||||
}
|
||||
if species_color < len(species_colors) {
|
||||
txt.print(species_colors[species_color])
|
||||
txt.spc()
|
||||
}
|
||||
if species_look < len(species_looks) {
|
||||
txt.print(species_looks[species_look])
|
||||
txt.spc()
|
||||
}
|
||||
if species_kind < len(species_kinds) {
|
||||
txt.print(species_kinds[species_kind])
|
||||
}
|
||||
} else {
|
||||
txt.print("Human Colonials")
|
||||
}
|
||||
txt.nl()
|
||||
txt.print(soup())
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
sub print_name_uppercase() {
|
||||
ubyte c
|
||||
for c in name
|
||||
txt.chrout(c | 32)
|
||||
}
|
||||
|
||||
asmsub getword(ubyte list @A, ubyte wordidx @Y) -> uword @AY {
|
||||
%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
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
util9 {
|
||||
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 st) {
|
||||
repeat width - string.length(st) {
|
||||
txt.spc()
|
||||
}
|
||||
txt.print(st)
|
||||
}
|
||||
|
||||
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {
|
||||
%asm {{
|
||||
jsr conv.uword2decimal
|
||||
lda conv.uword2decimal.decTenThousands
|
||||
ldy #0 ; have we started printing?
|
||||
cmp #'0'
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decThousands
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decHundreds
|
||||
cmp #'0'
|
||||
bne +
|
||||
cpy #0
|
||||
beq ++
|
||||
+ jsr c64.CHROUT
|
||||
iny
|
||||
+ lda conv.uword2decimal.decTens
|
||||
jsr c64.CHROUT
|
||||
lda #'.'
|
||||
jsr c64.CHROUT
|
||||
lda conv.uword2decimal.decOnes
|
||||
jsr c64.CHROUT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -86,23 +86,11 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
|
|||
DataType.ARRAY_UW -> "uword["
|
||||
DataType.ARRAY_W -> "word["
|
||||
DataType.ARRAY_F -> "float["
|
||||
DataType.STRUCT -> "" // the name of the struct is enough
|
||||
DataType.STRUCT -> "" // TODO STRUCT DOESN'T EXIST ANYMORE
|
||||
else -> "?????"
|
||||
}
|
||||
}
|
||||
|
||||
override fun visit(structDecl: StructDecl) {
|
||||
outputln("struct ${structDecl.name} {")
|
||||
scopelevel++
|
||||
for(decl in structDecl.statements) {
|
||||
outputi("")
|
||||
decl.accept(this)
|
||||
output("\n")
|
||||
}
|
||||
scopelevel--
|
||||
outputlni("}")
|
||||
}
|
||||
|
||||
override fun visit(decl: VarDecl) {
|
||||
|
||||
// if the vardecl is a parameter of a subroutine, don't output it again
|
||||
|
@ -116,9 +104,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
|
|||
VarDeclType.MEMORY -> output("&")
|
||||
}
|
||||
|
||||
if(decl.datatype==DataType.STRUCT && decl.struct!=null)
|
||||
output(decl.struct!!.name)
|
||||
|
||||
output(datatypeString(decl.datatype))
|
||||
if(decl.arraysize!=null) {
|
||||
decl.arraysize!!.indexExpr.accept(this)
|
||||
|
|
|
@ -124,18 +124,7 @@ interface INameScope {
|
|||
|
||||
fun lookup(scopedName: List<String>, localContext: Node) : Statement? {
|
||||
if(scopedName.size>1) {
|
||||
// a scoped name can a) refer to a member of a struct, or b) refer to a name in another module.
|
||||
// try the struct first.
|
||||
val thing = lookup(scopedName.dropLast(1), localContext) as? VarDecl
|
||||
val struct = thing?.struct
|
||||
if (struct != null) {
|
||||
if(struct.statements.any { (it as VarDecl).name == scopedName.last()}) {
|
||||
// return ref to the mangled name variable
|
||||
val mangled = mangledStructMemberName(thing.name, scopedName.last())
|
||||
return thing.definingScope().getLabelOrVariable(mangled)
|
||||
}
|
||||
}
|
||||
|
||||
// a scoped name refers to a name in another module.
|
||||
// it's a qualified name, look it up from the root of the module's namespace (consider all modules in the program)
|
||||
for(module in localContext.definingModule().program.modules) {
|
||||
var scope: INameScope? = module
|
||||
|
@ -297,7 +286,7 @@ class Program(val name: String,
|
|||
if(existing!=null)
|
||||
return existing
|
||||
|
||||
val decl = VarDecl(VarDeclType.VAR, DataType.STR, ZeropageWish.NOT_IN_ZEROPAGE, null, "string_${internedStrings.size}", null, string,
|
||||
val decl = VarDecl(VarDeclType.VAR, DataType.STR, ZeropageWish.NOT_IN_ZEROPAGE, null, "string_${internedStrings.size}", string,
|
||||
isArray = false, autogeneratedDontRemove = true, position = string.position)
|
||||
val internedStringsBlock = modules.first { it.name==internedStringsModuleName }.statements.first { it is Block && it.name == internedStringsModuleName}
|
||||
(internedStringsBlock as Block).statements.add(decl)
|
||||
|
@ -384,20 +373,6 @@ class GlobalNamespace(val modules: List<Module>, private val builtinFunctionName
|
|||
return builtinPlaceholder
|
||||
}
|
||||
|
||||
if(scopedName.size>1) {
|
||||
// a scoped name can a) refer to a member of a struct, or b) refer to a name in another module.
|
||||
// try the struct first.
|
||||
val thing = lookup(scopedName.dropLast(1), localContext) as? VarDecl
|
||||
val struct = thing?.struct
|
||||
if (struct != null) {
|
||||
if(struct.statements.any { (it as VarDecl).name == scopedName.last()}) {
|
||||
// return ref to the mangled name variable
|
||||
val mangled = mangledStructMemberName(thing.name, scopedName.last())
|
||||
return thing.definingScope().getLabelOrVariable(mangled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// special case: the do....until statement can also look INSIDE the anonymous scope
|
||||
if(localContext.parent.parent is UntilLoop) {
|
||||
val symbolFromInnerScope = (localContext.parent.parent as UntilLoop).body.lookup(scopedName, localContext)
|
||||
|
@ -407,7 +382,7 @@ class GlobalNamespace(val modules: List<Module>, private val builtinFunctionName
|
|||
|
||||
// lookup something from the module.
|
||||
return when (val stmt = localContext.definingModule().lookup(scopedName, localContext)) {
|
||||
is Label, is VarDecl, is Block, is Subroutine, is StructDecl -> stmt
|
||||
is Label, is VarDecl, is Block, is Subroutine -> stmt
|
||||
null -> null
|
||||
else -> throw SyntaxError("invalid identifier target type", stmt.position)
|
||||
}
|
||||
|
@ -423,10 +398,6 @@ object BuiltinFunctionScopePlaceholder : INameScope {
|
|||
}
|
||||
|
||||
|
||||
// prefix for struct member variables
|
||||
fun mangledStructMemberName(varName: String, memberName: String) = "prog8struct_${varName}_$memberName"
|
||||
|
||||
|
||||
fun Number.toHex(): String {
|
||||
// 0..15 -> "0".."15"
|
||||
// 16..255 -> "$10".."$ff"
|
||||
|
|
|
@ -66,7 +66,6 @@ private fun prog8Parser.VariabledeclarationContext.toAst(encoding: IStringEncodi
|
|||
if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE,
|
||||
vd.arrayindex()?.toAst(encoding),
|
||||
vd.varname.text,
|
||||
null,
|
||||
it.expression().toAst(encoding),
|
||||
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
||||
false,
|
||||
|
@ -74,37 +73,6 @@ private fun prog8Parser.VariabledeclarationContext.toAst(encoding: IStringEncodi
|
|||
)
|
||||
}
|
||||
|
||||
structvarinitializer()?.let {
|
||||
val vd = it.structvardecl()
|
||||
return VarDecl(
|
||||
VarDeclType.VAR,
|
||||
DataType.STRUCT,
|
||||
ZeropageWish.NOT_IN_ZEROPAGE,
|
||||
null,
|
||||
vd.varname.text,
|
||||
vd.structname.text,
|
||||
it.expression().toAst(encoding),
|
||||
isArray = false,
|
||||
autogeneratedDontRemove = false,
|
||||
position = it.toPosition()
|
||||
)
|
||||
}
|
||||
|
||||
structvardecl()?.let {
|
||||
return VarDecl(
|
||||
VarDeclType.VAR,
|
||||
DataType.STRUCT,
|
||||
ZeropageWish.NOT_IN_ZEROPAGE,
|
||||
null,
|
||||
it.varname.text,
|
||||
it.structname.text,
|
||||
null,
|
||||
isArray = false,
|
||||
autogeneratedDontRemove = false,
|
||||
position = it.toPosition()
|
||||
)
|
||||
}
|
||||
|
||||
constdecl()?.let {
|
||||
val cvarinit = it.varinitializer()
|
||||
val vd = cvarinit.vardecl()
|
||||
|
@ -114,7 +82,6 @@ private fun prog8Parser.VariabledeclarationContext.toAst(encoding: IStringEncodi
|
|||
if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE,
|
||||
vd.arrayindex()?.toAst(encoding),
|
||||
vd.varname.text,
|
||||
null,
|
||||
cvarinit.expression().toAst(encoding),
|
||||
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
||||
false,
|
||||
|
@ -131,7 +98,6 @@ private fun prog8Parser.VariabledeclarationContext.toAst(encoding: IStringEncodi
|
|||
if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE,
|
||||
vd.arrayindex()?.toAst(encoding),
|
||||
vd.varname.text,
|
||||
null,
|
||||
mvarinit.expression().toAst(encoding),
|
||||
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
||||
false,
|
||||
|
@ -139,12 +105,6 @@ private fun prog8Parser.VariabledeclarationContext.toAst(encoding: IStringEncodi
|
|||
)
|
||||
}
|
||||
|
||||
structdecl()?.let {
|
||||
return StructDecl(it.identifier().text,
|
||||
it.vardecl().map { vd->vd.toAst(encoding) }.toMutableList(),
|
||||
toPosition())
|
||||
}
|
||||
|
||||
throw FatalAstException("weird variable decl $this")
|
||||
}
|
||||
|
||||
|
@ -639,7 +599,6 @@ private fun prog8Parser.VardeclContext.toAst(encoding: IStringEncoding): VarDecl
|
|||
arrayindex()?.toAst(encoding),
|
||||
varname.text,
|
||||
null,
|
||||
null,
|
||||
ARRAYSIG() != null || arrayindex() != null,
|
||||
false,
|
||||
toPosition()
|
||||
|
|
|
@ -786,27 +786,9 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
|
|||
override fun inferType(program: Program): InferredTypes.InferredType {
|
||||
return when (val targetStmt = targetStatement(program)) {
|
||||
is VarDecl -> InferredTypes.knownFor(targetStmt.datatype)
|
||||
is StructDecl -> InferredTypes.knownFor(DataType.STRUCT)
|
||||
else -> InferredTypes.InferredType.unknown()
|
||||
}
|
||||
}
|
||||
|
||||
fun memberOfStruct(program: Program) = this.targetVarDecl(program)?.struct
|
||||
|
||||
fun firstStructVarName(program: Program): String? {
|
||||
// take the name of the first struct member of the structvariable instead
|
||||
// if it's just a regular variable, return null.
|
||||
val struct = memberOfStruct(program) ?: return null
|
||||
val decl = targetVarDecl(program)!!
|
||||
if(decl.datatype!=DataType.STRUCT)
|
||||
return null
|
||||
|
||||
val firstStructMember = struct.nameOfFirstMember()
|
||||
// find the flattened var that belongs to this first struct member
|
||||
val firstVarName = listOf(decl.name, firstStructMember)
|
||||
val firstVar = definingScope().lookup(firstVarName, this) as VarDecl
|
||||
return firstVar.name
|
||||
}
|
||||
}
|
||||
|
||||
class FunctionCall(override var target: IdentifierReference,
|
||||
|
|
|
@ -161,16 +161,11 @@ open class VarDecl(val type: VarDeclType,
|
|||
val zeropage: ZeropageWish,
|
||||
var arraysize: ArrayIndex?,
|
||||
override val name: String,
|
||||
private val structName: String?,
|
||||
var value: Expression?,
|
||||
val isArray: Boolean,
|
||||
val autogeneratedDontRemove: Boolean,
|
||||
override val position: Position) : Statement(), ISymbolStatement {
|
||||
override lateinit var parent: Node
|
||||
var struct: StructDecl? = null // set later (because at parse time, we only know the name)
|
||||
private set
|
||||
var structHasBeenFlattened = false // set later
|
||||
private set
|
||||
var allowInitializeWithZero = true
|
||||
|
||||
// prefix for literal values that are turned into a variable on the heap
|
||||
|
@ -187,7 +182,7 @@ open class VarDecl(val type: VarDeclType,
|
|||
array.type.typeOrElse(DataType.STRUCT)
|
||||
val declaredType = ArrayElementTypes.getValue(arrayDt)
|
||||
val arraysize = ArrayIndex.forArray(array)
|
||||
return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, null, array,
|
||||
return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array,
|
||||
isArray = true, autogeneratedDontRemove = true, position = array.position)
|
||||
}
|
||||
|
||||
|
@ -221,16 +216,6 @@ open class VarDecl(val type: VarDeclType,
|
|||
this.parent = parent
|
||||
arraysize?.linkParents(this)
|
||||
value?.linkParents(this)
|
||||
if(structName!=null) {
|
||||
val structStmt = definingScope().lookup(listOf(structName), this)
|
||||
if(structStmt!=null) {
|
||||
val node = definingScope().lookup(listOf(structName), this)
|
||||
if(node is StructDecl)
|
||||
struct = node
|
||||
else
|
||||
datatypeErrors.add(SyntaxError("invalid datatype declaration", position))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||
|
@ -243,7 +228,7 @@ open class VarDecl(val type: VarDeclType,
|
|||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
|
||||
override fun toString(): String {
|
||||
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, struct=$structName, value=$value, pos=$position)"
|
||||
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)"
|
||||
}
|
||||
|
||||
fun zeroElementValue(): NumericLiteralValue {
|
||||
|
@ -253,45 +238,16 @@ open class VarDecl(val type: VarDeclType,
|
|||
throw IllegalArgumentException("attempt to get zero value for vardecl that shouldn't get it")
|
||||
}
|
||||
|
||||
fun flattenStructMembers(): MutableList<Statement> {
|
||||
val result = struct!!.statements.mapIndexed { index, statement ->
|
||||
val member = statement as VarDecl
|
||||
val initvalueOrig = if(value!=null) (value as ArrayLiteralValue).value[index] else null
|
||||
val initvalue = when(initvalueOrig) {
|
||||
is AddressOf -> initvalueOrig.copy()
|
||||
is ArrayIndexedExpression -> initvalueOrig.copy()
|
||||
is DirectMemoryRead -> initvalueOrig.copy()
|
||||
is IdentifierReference -> initvalueOrig.copy()
|
||||
else -> initvalueOrig
|
||||
}
|
||||
VarDecl(
|
||||
VarDeclType.VAR,
|
||||
member.datatype,
|
||||
ZeropageWish.NOT_IN_ZEROPAGE,
|
||||
member.arraysize,
|
||||
mangledStructMemberName(name, member.name),
|
||||
struct!!.name,
|
||||
initvalue,
|
||||
member.isArray,
|
||||
true,
|
||||
member.position
|
||||
)
|
||||
}.toMutableList<Statement>()
|
||||
structHasBeenFlattened = true
|
||||
return result
|
||||
}
|
||||
|
||||
fun copy(): VarDecl {
|
||||
val c = VarDecl(type, declaredDatatype, zeropage, arraysize, name, structName, value, isArray, autogeneratedDontRemove, position)
|
||||
val c = VarDecl(type, declaredDatatype, zeropage, arraysize, name, value, isArray, autogeneratedDontRemove, position)
|
||||
c.allowInitializeWithZero = this.allowInitializeWithZero
|
||||
c.structHasBeenFlattened = this.structHasBeenFlattened
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
// a vardecl used only for subroutine parameters
|
||||
class ParameterVarDecl(name: String, declaredDatatype: DataType, position: Position)
|
||||
: VarDecl(VarDeclType.VAR, declaredDatatype, ZeropageWish.DONTCARE, null, name, null, null, false, true, position)
|
||||
: VarDecl(VarDeclType.VAR, declaredDatatype, ZeropageWish.DONTCARE, null, name, null, false, true, position)
|
||||
|
||||
class ArrayIndex(var indexExpr: Expression,
|
||||
override val position: Position) : Node {
|
||||
|
@ -955,36 +911,6 @@ class WhenChoice(var values: MutableList<Expression>?, // if null, th
|
|||
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
}
|
||||
|
||||
class StructDecl(override val name: String,
|
||||
override var statements: MutableList<Statement>, // actually, only vardecls here
|
||||
override val position: Position): Statement(), INameScope {
|
||||
|
||||
override lateinit var parent: Node
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
this.statements.forEach { it.linkParents(this) }
|
||||
}
|
||||
|
||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||
require(replacement is Statement)
|
||||
val idx = statements.indexOfFirst { it===node }
|
||||
statements[idx] = replacement
|
||||
replacement.parent = this
|
||||
}
|
||||
|
||||
val numberOfElements: Int
|
||||
get() = this.statements.size
|
||||
|
||||
fun memsize(memsizer: IMemSizer) =
|
||||
statements.map { memsizer.memorySize((it as VarDecl).datatype) }.sum()
|
||||
|
||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
|
||||
fun nameOfFirstMember() = (statements.first() as VarDecl).name
|
||||
}
|
||||
|
||||
class DirectMemoryWrite(var addressExpression: Expression, override val position: Position) : Node {
|
||||
override lateinit var parent: Node
|
||||
|
||||
|
|
|
@ -111,7 +111,6 @@ abstract class AstWalker {
|
|||
open fun before(returnStmt: Return, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(scope: AnonymousScope, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(string: StringLiteralValue, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(structDecl: StructDecl, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(subroutine: Subroutine, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> = noModifications
|
||||
|
@ -152,7 +151,6 @@ abstract class AstWalker {
|
|||
open fun after(returnStmt: Return, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(scope: AnonymousScope, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(string: StringLiteralValue, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(structDecl: StructDecl, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> = noModifications
|
||||
|
@ -235,7 +233,6 @@ abstract class AstWalker {
|
|||
track(before(decl, parent), decl, parent)
|
||||
decl.value?.accept(this, decl)
|
||||
decl.arraysize?.accept(this, decl)
|
||||
decl.struct?.accept(this, decl)
|
||||
track(after(decl, parent), decl, parent)
|
||||
}
|
||||
|
||||
|
@ -435,11 +432,5 @@ abstract class AstWalker {
|
|||
whenChoice.statements.accept(this, whenChoice)
|
||||
track(after(whenChoice, parent), whenChoice, parent)
|
||||
}
|
||||
|
||||
fun visit(structDecl: StructDecl, parent: Node) {
|
||||
track(before(structDecl, parent), structDecl, parent)
|
||||
structDecl.statements.forEach { it.accept(this, structDecl) }
|
||||
track(after(structDecl, parent), structDecl, parent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ interface IAstVisitor {
|
|||
fun visit(decl: VarDecl) {
|
||||
decl.value?.accept(this)
|
||||
decl.arraysize?.accept(this)
|
||||
decl.struct?.accept(this)
|
||||
}
|
||||
|
||||
fun visit(subroutine: Subroutine) {
|
||||
|
@ -170,8 +169,4 @@ interface IAstVisitor {
|
|||
whenChoice.values?.forEach { it.accept(this) }
|
||||
whenChoice.statements.accept(this)
|
||||
}
|
||||
|
||||
fun visit(structDecl: StructDecl) {
|
||||
structDecl.statements.forEach { it.accept(this) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -330,39 +330,6 @@ read the syntax reference on strings.
|
|||
The same is true for arrays! So be careful to (re)initialize them if needed.
|
||||
|
||||
|
||||
Structs
|
||||
^^^^^^^
|
||||
|
||||
A struct is a group of one or more other variables.
|
||||
This allows you to reuse the definition and manipulate it as a whole.
|
||||
Individual variables in the struct are accessed as you would expect, just
|
||||
use a scoped name to refer to them: ``structvariable.membername``.
|
||||
|
||||
Structs are a bit limited in Prog8: you can only use numerical variables
|
||||
as member of a struct, so strings and arrays and other structs can not be part of a struct.
|
||||
Also, it is not possible to use a struct itself inside an array.
|
||||
Structs are mainly syntactic sugar for repeated groups of vardecls
|
||||
and assignments that belong together. However,
|
||||
*they are layed out in sequence in memory as the members are defined*
|
||||
which may be usefulif you want to pass pointers around.
|
||||
|
||||
To create a variable of a struct type you need to define the struct itself,
|
||||
and then create a variable with it::
|
||||
|
||||
struct Color {
|
||||
ubyte red
|
||||
ubyte green
|
||||
ubyte blue
|
||||
}
|
||||
|
||||
Color rgb = [255,122,0] ; note that struct initializer value is same as an array
|
||||
Color another ; the init value is optional, like arrays
|
||||
|
||||
another = rgb ; assign all of the values of rgb to another
|
||||
another.blue = 255 ; set a single member
|
||||
|
||||
|
||||
|
||||
Special types: const and memory-mapped
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -875,11 +842,6 @@ sizeof(name)
|
|||
For an 10 element array of floats, it is 50 (on the C-64, where a float is 5 bytes).
|
||||
Note: usually you will be interested in the number of elements in an array, use len() for that.
|
||||
|
||||
offsetof(membername)
|
||||
Number of bytes from the start of a struct variable that this member variable is located.
|
||||
For now, this only works on members of a declared struct variable and not yet on members
|
||||
referenced from the struct type itself. This might be improved in a future version of the language.
|
||||
|
||||
swap(x, y)
|
||||
Swap the values of numerical variables (or memory locations) x and y in a fast way.
|
||||
|
||||
|
|
|
@ -253,7 +253,6 @@ Various examples::
|
|||
byte[5] values = 255 ; initialize with five 255 bytes
|
||||
|
||||
word @zp zpword = 9999 ; prioritize this when selecting vars for zeropage storage
|
||||
Color rgb = {1,255,0} ; a struct variable with initial values
|
||||
|
||||
|
||||
Data types
|
||||
|
@ -387,27 +386,6 @@ Syntax is familiar with brackets: ``arrayvar[x]`` ::
|
|||
string[4] ; the fifth character (=byte) in the string
|
||||
|
||||
|
||||
Struct
|
||||
^^^^^^
|
||||
|
||||
A *struct* has to be defined to specify what its member variables are.
|
||||
There are one or more members::
|
||||
|
||||
struct <structname> {
|
||||
<vardecl>
|
||||
[ <vardecl> ...]
|
||||
}
|
||||
|
||||
You can only use numerical variables as member of a struct, so strings and arrays
|
||||
and other structs can not be part of a struct. Vice versa, a struct can not occur in an array.
|
||||
|
||||
After defining a struct you can use the name of the struct as a data type to declare variables with.
|
||||
|
||||
Struct variables can be assigned a struct literal value (also in their declaration as initial value)::
|
||||
|
||||
Color rgb = [255, 100, 0] ; note that the value is an array
|
||||
|
||||
|
||||
String
|
||||
^^^^^^
|
||||
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
TODO
|
||||
====
|
||||
|
||||
- get rid of Datatype.STRUCT
|
||||
- fix problem that unused vars are no longer properly removed
|
||||
- BeforeAsmGenerationAstChanger no longer needs to move vardecls??
|
||||
|
||||
|
||||
- simplify cx16.joystick_get2() once this cx16 rom issue is resolved: https://github.com/commanderx16/x16-rom/issues/203
|
||||
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
|
||||
- c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking)
|
||||
- get rid of all other TODO's in the code ;-)
|
||||
|
||||
|
|
|
@ -6,21 +6,17 @@
|
|||
|
||||
main {
|
||||
|
||||
struct Ball {
|
||||
float t
|
||||
ubyte color
|
||||
}
|
||||
|
||||
sub start() {
|
||||
|
||||
Ball ball
|
||||
float ball_t
|
||||
ubyte ball_color
|
||||
|
||||
repeat {
|
||||
ubyte xx=(sin(ball.t) * txt.DEFAULT_WIDTH/2.1) + txt.DEFAULT_WIDTH/2.0 as ubyte
|
||||
ubyte yy=(cos(ball.t*1.1356) * txt.DEFAULT_HEIGHT/2.1) + txt.DEFAULT_HEIGHT/2.0 as ubyte
|
||||
txt.setcc(xx, yy, 81, ball.color)
|
||||
ball.t += 0.08
|
||||
ball.color++
|
||||
ubyte xx=(sin(ball_t) * txt.DEFAULT_WIDTH/2.1) + txt.DEFAULT_WIDTH/2.0 as ubyte
|
||||
ubyte yy=(cos(ball_t*1.1356) * txt.DEFAULT_HEIGHT/2.1) + txt.DEFAULT_HEIGHT/2.0 as ubyte
|
||||
txt.setcc(xx, yy, 81, ball_color)
|
||||
ball_t += 0.08
|
||||
ball_color++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,21 +6,18 @@
|
|||
main {
|
||||
const uword screenwidth = txt.DEFAULT_WIDTH
|
||||
const uword screenheight = txt.DEFAULT_HEIGHT
|
||||
struct Ball {
|
||||
uword anglex
|
||||
uword angley
|
||||
ubyte color
|
||||
}
|
||||
uword anglex
|
||||
uword angley
|
||||
ubyte color
|
||||
|
||||
sub start() {
|
||||
Ball ball
|
||||
repeat {
|
||||
ubyte x = msb(sin8u(msb(ball.anglex)) * screenwidth)
|
||||
ubyte y = msb(cos8u(msb(ball.angley)) * screenheight)
|
||||
txt.setcc(x, y, 81, ball.color)
|
||||
ball.anglex+=366
|
||||
ball.angley+=291
|
||||
ball.color++
|
||||
ubyte x = msb(sin8u(msb(anglex)) * screenwidth)
|
||||
ubyte y = msb(cos8u(msb(angley)) * screenheight)
|
||||
txt.setcc(x, y, 81, color)
|
||||
anglex+=366
|
||||
angley+=291
|
||||
color++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,26 @@
|
|||
%import conv
|
||||
%import gfx2
|
||||
%import textio
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
gfx2.screen_mode(6) ; highres 4c
|
||||
gfx2.text_charset(3)
|
||||
gfx2.text(10, 10, 1, @"Hello!")
|
||||
|
||||
c64.SETTIM(0,0,0)
|
||||
; TODO WHY AREN'T UNUSED VARS REMOVED ANY LONGER???
|
||||
|
||||
ubyte rr
|
||||
for rr in 0 to 2 {
|
||||
uword yy
|
||||
for yy in 20 to 420 {
|
||||
gfx2.horizontal_line(10, yy, 610, (lsb(yy>>3) + rr) & 3)
|
||||
}
|
||||
}
|
||||
|
||||
uword time = c64.RDTIM16()
|
||||
conv.str_uw(time)
|
||||
gfx2.text(100, 10, 1, conv.string_out)
|
||||
ubyte xx1
|
||||
ubyte yy1=22
|
||||
ubyte zz1=33
|
||||
|
||||
repeat {
|
||||
ubyte xx
|
||||
ubyte yy=xx
|
||||
ubyte aa
|
||||
ubyte bb
|
||||
ubyte cc
|
||||
ubyte dd
|
||||
}
|
||||
|
||||
repeat {
|
||||
xx=1
|
||||
yy=xx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,31 +74,14 @@ trader {
|
|||
str input = "??????????"
|
||||
ubyte num_chars
|
||||
|
||||
struct SaveData {
|
||||
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
|
||||
}
|
||||
SaveData savedata
|
||||
ubyte[23] savedata
|
||||
; format:
|
||||
; 0 ubyte galaxy
|
||||
; 1 ubyte planet
|
||||
; 2-18 ubyte cargo0..cargo16
|
||||
; 19 uword cash
|
||||
; 21 ubyte max_cargo
|
||||
; 22 ubyte fuel
|
||||
|
||||
sub do_load() {
|
||||
txt.print("\nLoading universe...")
|
||||
|
@ -111,22 +94,23 @@ trader {
|
|||
return
|
||||
}
|
||||
|
||||
ship.cash = savedata.cash
|
||||
ship.Max_cargo = savedata.max_cargo
|
||||
ship.fuel = savedata.fuel
|
||||
sys.memcopy(&savedata.cargo0, ship.cargohold, len(ship.cargohold))
|
||||
galaxy.travel_to(savedata.galaxy, savedata.planet)
|
||||
ship.cash = mkword(savedata[20], savedata[19])
|
||||
ship.Max_cargo = savedata[21]
|
||||
ship.fuel = savedata[22]
|
||||
sys.memcopy(&savedata + 2, ship.cargohold, len(ship.cargohold))
|
||||
galaxy.travel_to(savedata[0], savedata[1])
|
||||
|
||||
planet.display(false, 0)
|
||||
}
|
||||
|
||||
sub do_save() {
|
||||
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))
|
||||
savedata[0] = galaxy.number
|
||||
savedata[1] = planet.number
|
||||
savedata[19] = lsb(ship.cash)
|
||||
savedata[20] = msb(ship.cash)
|
||||
savedata[21] = ship.Max_cargo
|
||||
savedata[22] = ship.fuel
|
||||
sys.memcopy(ship.cargohold, &savedata + 2, len(ship.cargohold))
|
||||
|
||||
txt.print("\nSaving universe...")
|
||||
diskio.delete(8, Savegame)
|
||||
|
|
|
@ -109,12 +109,9 @@ statement :
|
|||
|
||||
variabledeclaration :
|
||||
varinitializer
|
||||
| structvarinitializer
|
||||
| vardecl
|
||||
| structvardecl
|
||||
| constdecl
|
||||
| memoryvardecl
|
||||
| structdecl
|
||||
;
|
||||
|
||||
|
||||
|
@ -139,18 +136,12 @@ directivearg : stringliteral | identifier | integerliteral ;
|
|||
|
||||
vardecl: datatype ZEROPAGE? (arrayindex | ARRAYSIG) ? varname=identifier ;
|
||||
|
||||
structvardecl: structname=identifier varname=identifier ;
|
||||
|
||||
varinitializer : vardecl '=' expression ;
|
||||
|
||||
structvarinitializer : structvardecl '=' expression ;
|
||||
|
||||
constdecl: 'const' varinitializer ;
|
||||
|
||||
memoryvardecl: ADDRESS_OF varinitializer;
|
||||
|
||||
structdecl: 'struct' identifier '{' EOL vardecl ( EOL vardecl)* EOL? '}' EOL;
|
||||
|
||||
datatype: 'ubyte' | 'byte' | 'uword' | 'word' | 'float' | 'str' ;
|
||||
|
||||
arrayindex: '[' expression ']' ;
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
</options>
|
||||
<keywords keywords="&;->;@;\$;and;as;asmsub;break;clobbers;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%import;%launcher;%option;%output;%target;%zeropage;%zpreserved" />
|
||||
<keywords3 keywords="byte;const;float;str;struct;ubyte;uword;void;word;zp" />
|
||||
<keywords4 keywords="abs;acos;all;any;asin;atan;avg;callfar;callrom;ceil;cmp;cos;cos16;cos16u;cos8;cos8u;deg;floor;len;ln;log2;lsb;lsl;lsr;max;memory;min;mkword;msb;offsetof;peek;peekw;poke;pokew;rad;reverse;rnd;rndf;rndw;rol;rol2;ror;ror2;round;sgn;sin;sin16;sin16u;sin8;sin8u;sizeof;sort;sqrt;sqrt16;sum;swap;tan" />
|
||||
<keywords3 keywords="byte;const;float;str;ubyte;uword;void;word;zp" />
|
||||
<keywords4 keywords="abs;acos;all;any;asin;atan;avg;callfar;callrom;ceil;cmp;cos;cos16;cos16u;cos8;cos8u;deg;floor;len;ln;log2;lsb;lsl;lsr;max;memory;min;mkword;msb;peek;peekw;poke;pokew;rad;reverse;rnd;rndf;rndw;rol;rol2;ror;ror2;round;sgn;sin;sin16;sin16u;sin8;sin8u;sizeof;sort;sqrt;sqrt16;sum;swap;tan" />
|
||||
</highlighting>
|
||||
<extensionMap>
|
||||
<mapping ext="p8" />
|
||||
|
|
|
@ -44,7 +44,6 @@ syn region prog8ArrayType matchgroup=prog8Type
|
|||
\ transparent
|
||||
syn keyword prog8StorageClass const
|
||||
syn match prog8StorageClass "\(^\|\s\)@zp\>"
|
||||
syn keyword prog8Structure struct
|
||||
|
||||
syn region prog8Block start="{" end="}" transparent
|
||||
syn region prog8Expression start="(" end=")" transparent
|
||||
|
|
|
@ -16,7 +16,7 @@ syn keyword prog8BuiltInFunc any all len max min reverse sum sort
|
|||
|
||||
" Miscellaneous functions
|
||||
syn keyword prog8BuiltInFunc cmp lsb msb mkword peek peekw poke pokew rnd rndw
|
||||
syn keyword prog8BuiltInFunc rndf rol rol2 ror ror2 sizeof offsetof
|
||||
syn keyword prog8BuiltInFunc rndf rol rol2 ror ror2 sizeof
|
||||
syn keyword prog8BuiltInFunc swap memory callfar callrom
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user