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