bytecode.cpp and surrounding ideas
This commit is contained in:
parent
b21b5079a9
commit
ddc9e192a7
76
ideas/a.txt
Normal file
76
ideas/a.txt
Normal file
@ -0,0 +1,76 @@
|
||||
TopVar[0]
|
||||
TopVar[1]
|
||||
TopVar[2]
|
||||
TopVar[3]
|
||||
Vektator -> [0.. (2 byte index)
|
||||
V
|
||||
[t1_A, t1_B, t2_Z, t2_Y, t2_U]
|
||||
|
||||
// flottánként van a vektátor memóriaterület, ha túl sok, nem engedünk játszani
|
||||
|
||||
enum BYTEKIND
|
||||
{
|
||||
IGNORE,
|
||||
NIL,
|
||||
NUMBER,
|
||||
INPUT,
|
||||
OUTPUT,
|
||||
OPCODE,
|
||||
ENGINE,
|
||||
HARDWARE,
|
||||
COMM,
|
||||
};
|
||||
|
||||
void f(game_state *gs, ship_tile *st, uint8_t byte_code[4], int byte_index);
|
||||
|
||||
bool validate(uint8_t *byte_code, byte_code_element *byte_info)
|
||||
{
|
||||
if (bk <= OUTPUT) return true;
|
||||
bool ok = true;
|
||||
for (int i = 1; i < 4; ++i)
|
||||
{
|
||||
switch(byte_info->at(i))
|
||||
{
|
||||
case IGNORE: return true;
|
||||
case NUMBER: ok &= validate_number(byte_code[i]);
|
||||
case OUTPUT: ok &= validate_variable(byte_code[i]);
|
||||
case INPUT: ok &= (validate_number(byte_code[i]) || validate_variable(byte_code[i]));
|
||||
case HARDWARE: ok &= hardwares.find(byte_code[i]) != hardwares.end();
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define LEVEL 0
|
||||
{OPCODE, "HULL", 'H', hull, NUMBER, NUMBER, NUMBER}, // HULL <durability: 0..1> <energy gen> <energy store (between turns)> - first command
|
||||
{OPCODE, "PAR", 'p', par, OUTPUT, NUMBER, NUMBER}, // PAR <persistant name> <low limit> <high limit> after HULL, before actual code
|
||||
{OPCODE, "MUL", '*', mul},
|
||||
{OPCODE, "ADD", '+', add},
|
||||
{OPCODE, "ENGINE", 'e', nextbyte?, ENGINE, IGNORE, IGNORE},
|
||||
{OPCODE, "HW", 'h', nextbyte?, HARDWARE, IGNORE, IGNORE},
|
||||
{OPCODE, "COMM", 'c', nextbyte?, COMM, IGNORE, IGNORE},
|
||||
#define LEVEL 1
|
||||
// ENGINE - if multiple ones are set, we choose randomly from the options given
|
||||
{ENGINE, "north", 'N', NIL, NIL, IGNORE},
|
||||
{"east", 'E'},
|
||||
{"west", 'W'},
|
||||
{"south", 'S'},
|
||||
|
||||
|
||||
// HARDWARE
|
||||
{HARDWARE, "cannon", 'c', cannon, INPUT, INPUT, IGNORE}, // destroys target ("returns" bool)
|
||||
{"sonar", 's'}, // shows tile + mine (radar)
|
||||
{"tracer", 't'}, // ray-trace a line ("returns" bool), doesn't detect mines
|
||||
{"jumbler", 'j'}, // randomizes parameters on target
|
||||
{"disruptor", 'd'}, // counters cannons
|
||||
{"mine", 'm'}, // places a mine (on your tile) that activates after P1 turns. When active and hit, it explodes
|
||||
{"blow", 'b'}, // blows mines towards a line (move to the next tile that is hit by the line) (should start from the end, so multiple mines don't hit each other)
|
||||
|
||||
// COMM
|
||||
{"write", 'w'}, // HW write <channel> <info> (write a number to a ship-wide channel)
|
||||
{"read", 'r'}, // HW read <channel> <output> (read a number from a ship-wide channel)
|
||||
|
||||
{"gps", 'G'}, // HW gps <output_X> <output_Y> (gets global coordinates)
|
||||
{"fwrite", 'W'}, // HW write <channel> <info> (write a number to a fleet-wide channel)
|
||||
{"fread", 'R'}, // HW read <channel> <output> (read a number to a fleet-wide channel)
|
131
ideas/bytecode.cpp
Normal file
131
ideas/bytecode.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
std::string code = "HULL 1 5 10\nPAR A 1 3 \r\nENGINE north\nMUL a A 2\nADD a a 1\nHW cannon A a\nCOMM write 1 5\n";
|
||||
|
||||
#define BYTEINFO(bytekind, command, bytecode, func, p1k, p2k, p3k) {command, bytecode},
|
||||
static std::map<std::string, uint8_t> keywords = {
|
||||
#include "opcode_list.h"
|
||||
#include "enginecode_list.h"
|
||||
#include "hardwarecode_list.h"
|
||||
#include "commcode_list.h"
|
||||
};
|
||||
|
||||
|
||||
void write_file_bytes(const char* filename, std::vector<uint8_t>& bytes)
|
||||
{
|
||||
FILE * f = fopen(filename, "w");
|
||||
fwrite(&bytes[0], 1, bytes.size(), f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
bool add_if_number(std::vector<uint8_t> &result_code, const std::string &token)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
int num = 0;
|
||||
int sign = 1;
|
||||
if (token.length() > 4) return false;
|
||||
if (token[0] == '-')
|
||||
{
|
||||
sign = -1;
|
||||
++i;
|
||||
}
|
||||
else if (token[0] == '+')
|
||||
{
|
||||
++i;
|
||||
}
|
||||
if (i >= token.length()) return false;
|
||||
|
||||
while(i < token.length())
|
||||
{
|
||||
char c = token[i];
|
||||
if (c >= '0' && c<='9')
|
||||
{
|
||||
num = num * 10 + c - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (num > 100) return false;
|
||||
num = sign * num + 0x99; //0 -> 0x99, 1 -> 0x9A, 2 -> 0x9B, ... (variables -> [0..52])
|
||||
result_code.push_back((uint8_t)num);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool add_if_variable(std::vector<uint8_t> &result_code, const std::string &token)
|
||||
{
|
||||
if (token.length() != 1) return false;
|
||||
uint8_t c = token[0];
|
||||
if (c >= 'a' && c <= 'z')
|
||||
{
|
||||
result_code.push_back(c - 'a');
|
||||
return true;
|
||||
}
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
{
|
||||
result_code.push_back(c - 'A' + 'z' - 'a' + 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool add_if_keyword(std::vector<uint8_t> &result_code, const std::string &token)
|
||||
{
|
||||
auto token_it = keywords.find(token);
|
||||
if (token_it == keywords.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result_code.push_back(token_it->second);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<uint8_t> result_code;
|
||||
unsigned int start = 0;
|
||||
int remaining = 0;
|
||||
for (unsigned int i = 0; i<code.length(); ++i)
|
||||
{
|
||||
if (isspace(code[i]))
|
||||
{
|
||||
if (start < i)
|
||||
{
|
||||
remaining = (remaining + 3) % 4;
|
||||
std::string token = code.substr(start, i - start);
|
||||
printf("%s %d\n", token.c_str(), remaining);
|
||||
|
||||
if (!add_if_variable(result_code, token)
|
||||
&& !add_if_number(result_code, token)
|
||||
&& !add_if_keyword(result_code, token)
|
||||
)
|
||||
{
|
||||
printf("Unknown token: %s\n", token.c_str());
|
||||
result_code.push_back('?');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (code[i] == '\n')
|
||||
{
|
||||
for (int j = 0; j< remaining; ++j)
|
||||
{
|
||||
printf("NULL\n");
|
||||
result_code.push_back(0);
|
||||
}
|
||||
remaining = 0;
|
||||
}
|
||||
start = i + 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
write_file_bytes("bytecode.sbc", result_code);
|
||||
}
|
17
ideas/bytekind.h
Normal file
17
ideas/bytekind.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef __BYTEKIND__
|
||||
#define __BYTEKIND__
|
||||
|
||||
enum class BYTEKIND
|
||||
{
|
||||
IGNORE,
|
||||
NIL,
|
||||
NUMBER,
|
||||
INPUT,
|
||||
OUTPUT,
|
||||
OPCODE,
|
||||
ENGINE,
|
||||
HARDWARE,
|
||||
COMM,
|
||||
};
|
||||
|
||||
#endif
|
5
ideas/commcode_list.h
Normal file
5
ideas/commcode_list.h
Normal file
@ -0,0 +1,5 @@
|
||||
BYTEINFO(COMM, "write", 'w', ship_write, INPUT, INPUT, IGNORE) // COMM write <info> <channel> (write a number to a ship-wide channel)
|
||||
BYTEINFO(COMM, "read", 'r', ship_read, OUTPUT, INPUT, IGNORE) // COMM read <output> <channel> (read a number from a ship-wide channel)
|
||||
BYTEINFO(COMM, "gps", 'G', gps, OUTPUT, OUTPUT, IGNORE) // COMM gps <output_X> <output_Y> (gets global coordinates)
|
||||
BYTEINFO(COMM, "fwrite", 'W', fleet_write, INPUT, INPUT, IGNORE) // COMM write <info> <channel> (write a number to a fleet-wide channel)
|
||||
BYTEINFO(COMM, "fread", 'R', fleet_read, OUTPUT, INPUT, IGNORE) // COMM read <output> <channel> (read a number to a fleet-wide channel)
|
4
ideas/enginecode_list.h
Normal file
4
ideas/enginecode_list.h
Normal file
@ -0,0 +1,4 @@
|
||||
BYTEINFO(ENGINE, "north", 'N', north, IGNORE, IGNORE, IGNORE)
|
||||
BYTEINFO(ENGINE, "east", 'E', north, IGNORE, IGNORE, IGNORE)
|
||||
BYTEINFO(ENGINE, "west", 'W', north, IGNORE, IGNORE, IGNORE)
|
||||
BYTEINFO(ENGINE, "south", 'S', north, IGNORE, IGNORE, IGNORE)
|
8
ideas/hardwarecode_list.h
Normal file
8
ideas/hardwarecode_list.h
Normal file
@ -0,0 +1,8 @@
|
||||
BYTEINFO(HARDWARE, "cannon", 'c', cannon, INPUT, INPUT, IGNORE) // destroys target ("returns" bool)
|
||||
BYTEINFO(HARDWARE, "sonar", 's', sonar, INPUT, INPUT, IGNORE) // shows tile + mine (radar) (or only say if it is something on the tile? - the turn the command was given, or the next turn?
|
||||
BYTEINFO(HARDWARE, "tracer", 't', tracer, INPUT, INPUT, IGNORE) // ray-trace a line ("returns" bool), doesn't detect mines
|
||||
BYTEINFO(HARDWARE, "jumbler", 'j', jumbler, INPUT, INPUT, IGNORE) // randomizes parameters on target
|
||||
BYTEINFO(HARDWARE, "disruptor", 'd', disruptor, INPUT, INPUT, IGNORE) // counters cannons
|
||||
BYTEINFO(HARDWARE, "mine", 'm', mine, INPUT, INPUT, IGNORE) // places a mine (on your tile) that activates after P1 turns. When active and hit, it explodes
|
||||
BYTEINFO(HARDWARE, "blow", 'b', blow, INPUT, INPUT, IGNORE) // blows mines towards a line (move to the next tile that is hit by the line) (should start from the end, so multiple mines don't hit each other)
|
||||
|
20
ideas/opcode_list.h
Normal file
20
ideas/opcode_list.h
Normal file
@ -0,0 +1,20 @@
|
||||
BYTEINFO(OPCODE, "HULL", 'H', hull, NUMBER, NUMBER, NUMBER) // HULL <durability: 0..1> <energy gen> <energy store (between turns)> - first command
|
||||
BYTEINFO(OPCODE, "PAR", 'p', par, OUTPUT, NUMBER, NUMBER) // PAR <persistant name> <low limit> <high limit> after HULL, before actual code
|
||||
BYTEINFO(OPCODE, "MUL", '*', mul, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "ADD", '+', add, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "SUB", '-', sub, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "DIV", '/', div, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "SET", ':', set, OUTPUT, INPUT, IGNORE)
|
||||
BYTEINFO(OPCODE, "EQ", '=', eq, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "LESS", '<', less, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "MORE", '>', more, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "NOT", '!', not_op, OUTPUT, INPUT, IGNORE)
|
||||
BYTEINFO(OPCODE, "OR", '|', or_op, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "AND", '&', and_op, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "XOR", 'x', xor_op, OUTPUT, INPUT, INPUT)
|
||||
BYTEINFO(OPCODE, "RAND", 'r', rand, OUTPUT, INPUT, INPUT) // random number between P1 and P2 - should we include p2?
|
||||
BYTEINFO(OPCODE, "SKIP", 's', skip, INPUT, IGNORE, IGNORE) // SKIP 1 skips the next instruction (4 bytes), SKIP 0 = NOP, SKIP 10 skips the next 10 instructions. P1 >= 0
|
||||
BYTEINFO(OPCODE, "STOP", 'S', stop, IGNORE, IGNORE, IGNORE) // equivalent to SKIP infinite
|
||||
BYTEINFO(OPCODE, "ENGINE", 'e', engine, ENGINE, NIL, NIL) // ENGINE - if multiple ones are set, we choose randomly from the options given
|
||||
BYTEINFO(OPCODE, "HW", 'h', hardware, HARDWARE, IGNORE, IGNORE)
|
||||
BYTEINFO(OPCODE, "COMM", 'c', comm, COMM, IGNORE, IGNORE)
|
Loading…
x
Reference in New Issue
Block a user