ld41-sim_shitty/game/game.gd

250 lines
6.9 KiB
GDScript

extends Node
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var command_registry = Dictionary();
var command_history = []
export(bool) var debug = false
export(NodePath) var level_path = 'res://levels/sample/level.tscn'
var level = null
export(float) var turn_max_length = 60.0 # Seconds
var turn_time_left = -1.0
export(int) var population_start = 10
export(int) var jobs_start = 0
export(int) var food_start = 20
export(int) var resources_start = 0
export(int) var effort_start = 20
export(int) var goods_start = 0
var game_resources = {
'population': population_start,
'jobs': jobs_start,
'food': food_start,
'resources': resources_start,
'effort': effort_start,
'goods': goods_start,
}
var turns = 0
var build_regex = RegEx.new()
var set_resource_regex = RegEx.new()
# Game rules ish
export(bool) var advance_turn_on_successful_command = true
var game_object_registry = {
# TileMap ID. this is a crap way. but hey. do it fast.
2: {
"name": 'road',
},
3: {
"name": 'road',
},
4: {
'name': 'road',
},
5: {
'name': 'road',
},
6: {
'name': 'bridge',
},
7: {
'name': 'house'
},
8: {
"name": 'farm',
"node_path": 'N/A',
}
}
func _ready():
# Called every time the node is added to the scene.
# Initialization here
self.register_command('help', funcref(self, "command_help"))
self.build_regex.compile("build (?<object_id>[a-z_]*) (?<x>\\d+),(?<y>\\d+)")
self.register_command('build', funcref(self, "command_build"))
self.register_command('skip', funcref(self, 'command_skip'))
self.set_level(self.level_path)
if not self.debug:
get_node('ui/left sidebar/toggleWorldButton').hide()
if self.debug:
self.register_command('set_resource', funcref(self, 'command_set_resource'))
self.set_resource_regex.compile('set_resource (?<resource_name>[a-z_]*) (?<value>\\d+)')
get_node('ui/right sidebar/resources').update_resources(self.game_resources)
func set_level(path):
self.level = load(self.level_path).instance()
self.level.hide()
# Display?
get_node('world').add_child(self.level)
get_node('ui/right sidebar/MapSizeContainer').set_level_size(self.level.get_level_size())
# Set objects / simulation parameters.
# Start time
self.turn_time_left = self.turn_max_length
get_node('ui/right sidebar/timer').set_time_max(self.turn_max_length)
self.update_timer()
func _process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
self.turn_time_left -= delta
if self.turn_time_left <= 0.0:
self.advance_turn()
self.update_timer()
func advance_turn():
self.turn_time_left = self.turn_max_length
# Find people who can't get to jobs
# Find unfilled jobs
# Report unconnected buildings
# Update stats: consume food, word, etc.
self.turns += 1
func update_timer():
get_node('ui/right sidebar/timer').set_time_left(self.turn_time_left)
# A player has hit enter
func _on_prompt_text_entered(new_text):
history_append(new_text)
if new_text:
run_command(new_text)
# @TODO Run the command
get_node('ui/prompt').clear()
func history_append(text, is_command_result = false, return_code = 0):
var n = get_node('ui/ViewportContainer/history')
if not n:
return
if is_command_result:
if return_code != 0:
n.push_color(Color(1.0, 0.0, 0.0, 1.0))
n.add_text(' > (%d) %s' %[return_code, text])
if return_code != 0:
n.pop()
else:
n.add_text("$ " + text)
n.newline()
func history_search():
pass
func run_command(text):
var result;
var callback = parse_command(text)
if not callback[1]:
result = [-1, 'Command "%s" not found' % callback[0]]
else:
result = callback[1].call_func(text)
self.history_append(result[1], true, result[0])
# Possibly advance the turn depending on the game rule.
if self.advance_turn_on_successful_command && result[0] == 0:
self.advance_turn()
func parse_command(text):
var a = text.split(' ')
if self.command_registry.has(a[0]):
return [a[0], self.command_registry[a[0]]]
return [a[0], false]
func register_command(name, callback):
self.command_registry[name] = callback;
func remove_command(name):
if self.command_registry.has(name):
self.command_registry.erase(name);
func command_help(text):
print("received command: '%s'" % text)
return [0, 'no!']
func command_set_resource(text):
var r = self.set_resource_regex.search(text)
if r == null:
return [-1, 'set_resource command could not match arguments. Format: set_resource <resource_name> <value>']
var resource_name = r.get_string(1)
if ! self.game_resources.has(resource_name):
return [-2, 'Resource "%s" does not exist' %resource_name]
var value = int(r.get_string(2))
self.set_game_resource(resource_name, value)
return [0, 'Set resource "%s" to %d' %[resource_name, value]]
func set_game_resource(name, value):
self.game_resources[name] = value
get_node('ui/right sidebar/resources').update_resources(self.game_resources)
func command_build(text):
var r = self.build_regex.search(text)
if r == null:
return [-1, 'Build command could not match arguments. Format: build <object_id> <x>,<y>']
var object_id = _get_obj_id_by_name(r.get_string(1))
if object_id == null:
return [-3, "Object with id '%s' is not registered" % r.get_string(1)]
var p = Vector2(int(r.get_string(2)), int(r.get_string(3)))
if not _is_in_level(p):
return [-4, "Point %d,%d is not in current level" %[p.x, p.y]]
var obj_exists = _obj_exists_in_level(p)
if obj_exists:
var obj_name = self.game_object_registry[_obj_in_level(p)]['name']
return [-5, "Object %s already exists at %d, %d" % [obj_name, p.x, p.y]]
# Check if base terrain is valid.
var terrain_object_id = self.level.get_node('terrain').get_cellv(p)
if terrain_object_id == -1:
return [-6, "No terrain underneath point at %d,%d" %[p.x, p.y]]
# grass
if terrain_object_id == 0 && object_id == 6:
return [-7, "Can not build over water at %d,%d" %[p.x, p.y]]
if terrain_object_id == 1 && object_id != 6:
return [-8, "Can not build over grass at %d,%d" %[p.x, p.y]]
# (optional) check resources
# Build
self.level.get_node('objects').set_cellv(p, object_id)
# (optional) spend resources
return [0, 'Built %s at %d,%d' % [self.game_object_registry[object_id]['name'], p.x, p.y]]
func _is_in_level(v):
if v.x >= self.level.origin.x and v.x <= self.level.origin.x + self.level.width and \
v.y >= self.level.origin.y and v.y <= self.level.origin.y + self.level.height:
return true
return false
func _get_obj_id_by_name(n):
for i in self.game_object_registry.keys():
if self.game_object_registry[i]['name'] == n:
return i
return null
func _obj_in_level(v):
var c = self.level.get_node('objects').get_cellv(v)
if c == -1:
return null
return c
func _obj_exists_in_level(v):
if _obj_in_level(v) != null:
return true
return false
func _on_toggleWorldButton_toggled(button_pressed):
print(button_pressed)
if self.level.is_visible_in_tree():
self.level.hide()
else:
self.level.show()
func command_skip(t):
self.advance_turn()
return [0, 'OK']
func _on_timer_skip_presssed():
print('a')
self.advance_turn()