Initial
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,15 @@
|
||||
import math
|
||||
import ztime
|
||||
|
||||
class Action:
|
||||
def __init__(self, msg, start_time, end_time):
|
||||
self.msg = msg
|
||||
self.start_time = start_time # Time object
|
||||
self.end_time = end_time # Time object
|
||||
def is_running(self, cur_time):
|
||||
return cur_time < self.end_time
|
||||
def is_done(self, cur_time):
|
||||
return cur_time >= self.end_time
|
||||
def get_msg(self):
|
||||
return self.msg
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import action
|
||||
|
||||
class Agent:
|
||||
def __init__(self, name, stats,
|
||||
idle_message="Idle",
|
||||
action=None):
|
||||
self.name = name
|
||||
self.stats = stats
|
||||
self.idle_message = idle_message
|
||||
self.action = action
|
||||
def get_stat(self, stat_name):
|
||||
return self.stats[stat_name]
|
||||
def change_stat(self, stat_name, amt):
|
||||
stat = self.stats[stat_name]
|
||||
stat.change_index(amt)
|
||||
def get_name(self):
|
||||
return self.name
|
||||
def get_action(self):
|
||||
return self.action
|
||||
def set_action(self, action):
|
||||
self.action = action
|
||||
def update_action(self, cur_time):
|
||||
if self.action is not None:
|
||||
if self.action.is_done(cur_time):
|
||||
self.action = None
|
||||
def is_idle(self):
|
||||
return self.action is None
|
||||
def get_idle_message(self):
|
||||
return self.idle_message
|
||||
def get_action_message(self):
|
||||
if self.is_idle():
|
||||
return self.idle_message
|
||||
else:
|
||||
return self.action.get_msg()
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
class Stat:
|
||||
def __init__(self, name, values, index=0):
|
||||
self.name = name
|
||||
self.values = values
|
||||
self.index = index
|
||||
def get_value(self):
|
||||
return self.values[self.index]
|
||||
def set_index(self, i):
|
||||
self.index = i
|
||||
if self.index < 0:
|
||||
self.index = (self.index+len(self.values))%len(self.values)
|
||||
if self.index >= len(self.values):
|
||||
self.index = self.index%len(self.values)
|
||||
def change_index(self, delta):
|
||||
new_index = self.index+delta
|
||||
self.set_index(new_index)
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import enum
|
||||
import ztime
|
||||
import action
|
||||
from defs import STATS
|
||||
|
||||
|
||||
def tick_decisionsys(myagent, curtime):
|
||||
pass
|
||||
|
||||
def make_decisionsys(myagent):
|
||||
pass
|
||||
@@ -0,0 +1,49 @@
|
||||
import math
|
||||
|
||||
# List of tuples
|
||||
# 0: Name of the speed
|
||||
# 1: Milliseconds between ticks of the clock
|
||||
# 2: How many minutes pass with each tick
|
||||
GAME_SPEEDS = [
|
||||
('paused',math.inf,0),
|
||||
('very slow', 1000, 1),
|
||||
('slow', 100, 1),
|
||||
('normal',10, 1),
|
||||
('fast',1, 4),
|
||||
('very fast', 1, 8)]
|
||||
|
||||
# Background and text color
|
||||
BG_COLOR = "lightblue1"
|
||||
FG_COLOR = "black"
|
||||
|
||||
|
||||
# You should modify this list of agent stats
|
||||
# keys must be strings
|
||||
# values should be lists
|
||||
# The stats below are just examples to give you
|
||||
# some inspiration. Come up with your own set
|
||||
# based on the theme/setting you imagine.
|
||||
STATS = {
|
||||
'location':['home','work','daycare','bar','park','jail'],
|
||||
'hungry':list(range(0,20)),
|
||||
'tired':list(range(0,5)),
|
||||
'bored':list(range(0,2)),
|
||||
'purpose':list(range(0,3)),
|
||||
'lonely':list(range(0,20)),
|
||||
'money':list(range(0,1000)),
|
||||
'dirty':list(range(0,5)),
|
||||
'sad':list(range(0,10)),
|
||||
'crazy':list(range(0,10)),
|
||||
'frustrated':list(range(0,10)),
|
||||
'lazy':list(range(0,10)),
|
||||
'confident':list(range(0,10)),
|
||||
'accomplished':list(range(0,10))
|
||||
}
|
||||
|
||||
# Probably don't change this line.
|
||||
STAT_NAMES = list(STATS.keys())
|
||||
|
||||
# Change if you want. I hope I don't get
|
||||
# 40 submissions all about an agent named, Jimbo.
|
||||
AGENT_NAME = 'Jimbo'
|
||||
START_TIME = 1800 # 6:00 AM Monday
|
||||
@@ -0,0 +1,244 @@
|
||||
import pygame
|
||||
import pygame.freetype
|
||||
import math
|
||||
import random
|
||||
import agent_stat
|
||||
import ztime
|
||||
import action
|
||||
import agent
|
||||
import decision
|
||||
from defs import *
|
||||
|
||||
# ###############################################################
|
||||
class Display:
|
||||
def __init__(self, screen, clock):
|
||||
self.screen = screen
|
||||
self.clock = clock
|
||||
self.run = True
|
||||
self.delta = 0
|
||||
self.font = None
|
||||
|
||||
def draw_gobj(self, gobj):
|
||||
pygame.draw.circle(
|
||||
self.screen,
|
||||
gobj.color,
|
||||
gobj.pos(),
|
||||
gobj.radius)
|
||||
def draw_text(self, msg, x, y, color):
|
||||
surface, rect = self.font.render(msg, color)
|
||||
self.screen.blit(surface, (x, y))
|
||||
def draw_line(self, p1, p2, color,width=1):
|
||||
pygame.draw.line(
|
||||
self.screen,
|
||||
color,
|
||||
p1,
|
||||
p2,
|
||||
width)
|
||||
|
||||
def init_display(sw, sh):
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((sw,sh))
|
||||
clock = pygame.time.Clock()
|
||||
display = Display(screen, clock)
|
||||
display.font = pygame.freetype.Font('JuliaMono-Bold.ttf', 18)
|
||||
pygame.key.set_repeat(200,100)
|
||||
return display
|
||||
|
||||
def wrap_text(text, font, width):
|
||||
splt_text = text.split()
|
||||
|
||||
lines = []
|
||||
|
||||
cur = 0
|
||||
line = ""
|
||||
|
||||
while cur < len(splt_text):
|
||||
new_line = ""
|
||||
if len(line) > 0:
|
||||
new_line = f"{line} {splt_text[cur]}"
|
||||
else:
|
||||
new_line = splt_text[cur]
|
||||
r = pygame.freetype.Font.get_rect(font, new_line)
|
||||
if r.width > width:
|
||||
lines.append(line)
|
||||
line = ""
|
||||
else:
|
||||
line = new_line
|
||||
cur += 1
|
||||
if len(line) > 0:
|
||||
lines.append(line)
|
||||
|
||||
return lines
|
||||
|
||||
# #################################################################
|
||||
|
||||
def MakeStats():
|
||||
stats = {}
|
||||
for n,vals in STATS.items():
|
||||
astat = agent_stat.Stat(n,vals)
|
||||
stats[n] = astat
|
||||
return stats
|
||||
|
||||
def MakeAgent(agent_name, cur_time):
|
||||
a = agent.Agent(
|
||||
agent_name,
|
||||
MakeStats(),
|
||||
f"{agent_name} is doin' nuthin'."
|
||||
)
|
||||
return a
|
||||
|
||||
def UpdateAgent(myagent, curtime):
|
||||
myagent.update_action(curtime)
|
||||
|
||||
def DrawUI(display,
|
||||
cur_time,
|
||||
myagent,
|
||||
winw, winh,
|
||||
stat_index,
|
||||
game_speed,
|
||||
decision_sys_running):
|
||||
display.draw_text(
|
||||
f"Day: {cur_time.day_of_week()}",
|
||||
10,10,FG_COLOR)
|
||||
display.draw_text(
|
||||
f"Hour: {cur_time.hour():02}",
|
||||
180,10,FG_COLOR)
|
||||
display.draw_text(
|
||||
f"Min: {cur_time.minit():02}",
|
||||
300,10,FG_COLOR)
|
||||
display.draw_text(
|
||||
f"{myagent.get_name()}'s stats",
|
||||
10,40,FG_COLOR)
|
||||
display.draw_text(
|
||||
f"Game: {game_speed[0]}",
|
||||
410,10,FG_COLOR)
|
||||
display.draw_text(
|
||||
f"Decision Sys: {decision_sys_running}",
|
||||
580,10,FG_COLOR)
|
||||
display.draw_line((400,0),(400,winh),"black",2)
|
||||
display.draw_text(
|
||||
f"{myagent.get_name()}'s Action",
|
||||
410,40,FG_COLOR)
|
||||
|
||||
wrapped_msg = wrap_text(myagent.get_action_message(),
|
||||
display.font, 380)
|
||||
y = 70
|
||||
for msg in wrapped_msg:
|
||||
display.draw_text(
|
||||
msg,
|
||||
410, y, FG_COLOR)
|
||||
y += 25
|
||||
|
||||
y = 70
|
||||
x = 10
|
||||
for i,name in enumerate(STAT_NAMES):
|
||||
s = myagent.get_stat(name)
|
||||
c = FG_COLOR
|
||||
if i == stat_index:
|
||||
c = 'red'
|
||||
display.draw_text(
|
||||
f"{name:<12} {s.get_value()}",
|
||||
x,y,c)
|
||||
y += 25
|
||||
if y+25 > winh:
|
||||
x += 200
|
||||
y = 70
|
||||
|
||||
def MakeDecisionSys(myagent):
|
||||
decision.make_decisionsys(myagent)
|
||||
|
||||
def CheckDecisionSys(myagent, curtime):
|
||||
decision.tick_decisionsys(myagent, curtime)
|
||||
|
||||
|
||||
def GameLoop(display, _agent, _time):
|
||||
|
||||
winw, winh = pygame.display.get_window_size()
|
||||
curtime = _time
|
||||
myagent = _agent
|
||||
stat_index = 0
|
||||
old_speed = 0
|
||||
sim_speed = 0
|
||||
time_last_tick = 0
|
||||
next_behavior_update = curtime
|
||||
decision_sys_running = False
|
||||
|
||||
# Here is where the behavior is created before the
|
||||
# game loop starts.
|
||||
MakeDecisionSys(myagent)
|
||||
|
||||
while display.run:
|
||||
ticks = display.clock.tick(60)
|
||||
dt = ticks / 1000
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
display.run = False
|
||||
elif event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_LEFT:
|
||||
myagent.change_stat(STAT_NAMES[stat_index],-1)
|
||||
elif event.key == pygame.K_RIGHT:
|
||||
myagent.change_stat(STAT_NAMES[stat_index],1)
|
||||
elif event.key == pygame.K_UP:
|
||||
stat_index = ((stat_index-1)+len(STAT_NAMES))%len(STAT_NAMES)
|
||||
elif event.key == pygame.K_DOWN:
|
||||
stat_index = (stat_index+1)%len(STAT_NAMES)
|
||||
elif event.key == pygame.K_LEFTBRACKET:
|
||||
if sim_speed > 0:
|
||||
sim_speed -= 1
|
||||
elif event.key == pygame.K_RIGHTBRACKET:
|
||||
if sim_speed < len(GAME_SPEEDS)-1:
|
||||
sim_speed += 1
|
||||
elif event.key == pygame.K_p:
|
||||
if sim_speed == 0:
|
||||
sim_speed = old_speed
|
||||
else:
|
||||
old_speed = sim_speed
|
||||
sim_speed = 0
|
||||
elif event.key == pygame.K_q:
|
||||
display.run = False
|
||||
elif event.key == pygame.K_d:
|
||||
curtime.tick(60*24)
|
||||
elif event.key == pygame.K_s:
|
||||
curtime.tick(-60*24)
|
||||
elif event.key == pygame.K_h:
|
||||
curtime.tick(60)
|
||||
elif event.key == pygame.K_g:
|
||||
curtime.tick(-60)
|
||||
elif event.key == pygame.K_m:
|
||||
curtime.tick(1)
|
||||
elif event.key == pygame.K_n:
|
||||
curtime.tick(-1)
|
||||
elif event.key == pygame.K_SPACE:
|
||||
decision_sys_running = not decision_sys_running
|
||||
|
||||
# This function call checks the agent's action. If the
|
||||
# action has expired, the agent is set to idle.
|
||||
UpdateAgent(myagent, curtime)
|
||||
|
||||
# Here is where the agent's behavior is checked.
|
||||
# and if necessary, is switched to another action.
|
||||
if decision_sys_running:
|
||||
CheckDecisionSys(myagent, curtime)
|
||||
|
||||
display.screen.fill(BG_COLOR)
|
||||
|
||||
DrawUI(display, curtime, myagent, winw, winh, stat_index,
|
||||
GAME_SPEEDS[sim_speed], decision_sys_running)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
if GAME_SPEEDS[sim_speed][1] - time_last_tick <= 0:
|
||||
curtime.tick(GAME_SPEEDS[sim_speed][2])
|
||||
time_last_tick = 0
|
||||
else:
|
||||
time_last_tick += ticks
|
||||
|
||||
def main():
|
||||
display = init_display(800,600)
|
||||
myagent = MakeAgent(AGENT_NAME, START_TIME)
|
||||
cur_time = ztime.Time(START_TIME)
|
||||
GameLoop(display, myagent, cur_time)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
import math
|
||||
|
||||
class Time:
|
||||
MINS_IN_HOUR = 60
|
||||
HOURS_IN_DAY = 24
|
||||
DAYS_IN_WEEK = 7
|
||||
DAYS_OF_WEEK = [
|
||||
'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
|
||||
'Friday', 'Saturday']
|
||||
def __init__(self, minute):
|
||||
self.minute = minute
|
||||
def __lt__(self, o):
|
||||
return self.minute < o.minute
|
||||
def __eq__(self, o):
|
||||
return self.minute == o.minute
|
||||
def __ge__(self, o):
|
||||
return self.minute >= o.minute
|
||||
def __add__(self, o):
|
||||
return Time(self.minute + o.minute)
|
||||
def __str__(self):
|
||||
return f"{self.day_of_week()} {self.hour():02}:{self.minit():02}"
|
||||
def minit(self):
|
||||
_min = self.minute % self.MINS_IN_HOUR
|
||||
return _min
|
||||
def hour(self):
|
||||
hour = (self.minute // self.MINS_IN_HOUR) % self.HOURS_IN_DAY
|
||||
return hour
|
||||
def day(self):
|
||||
day = (self.minute // (self.MINS_IN_HOUR*self.HOURS_IN_DAY)) % self.DAYS_IN_WEEK
|
||||
return day
|
||||
def day_of_week(self):
|
||||
return self.DAYS_OF_WEEK[self.day()]
|
||||
def tick(self, amt):
|
||||
self.minute += amt
|
||||
|
||||
def infinity():
|
||||
return Time(math.inf)
|
||||
Reference in New Issue
Block a user