Skip to content

Commit

Permalink
Add first draft of the python module and gymnasium-based state
Browse files Browse the repository at this point in the history
controller.
  • Loading branch information
sobomax committed Jan 16, 2024
1 parent 46c4412 commit 15ad649
Show file tree
Hide file tree
Showing 12 changed files with 479 additions and 1 deletion.
64 changes: 64 additions & 0 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# This is a basic workflow to help you get started with Actions

name: Check Python Integration

# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
branches:
pull_request:
branches:

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
python:
# The type of runner that the job will run on
runs-on: ubuntu-latest
env:
COMPILER: ${{ matrix.compiler }}

strategy:
matrix:
compiler: ['gcc-10', 'gcc-11', 'gcc-12', 'gcc-13', 'gcc-14', 'clang-13', 'clang-14', 'clang-15', 'clang-16']

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v3
with:
submodules: 'recursive'

- name: before_install
run: sudo -H DEBIAN_FRONTEND=noninteractive apt-get update

- name: Workaround for tar not being able to access /var/cache/apt/archives
run: sudo chmod u+s "$(command -v tar)"

# Cache the apt-get packages
- name: Cache apt-get packages
uses: actions/cache@v3
with:
path: /var/cache/apt/archives
key: ${{ matrix.os }}-apt-get-${{ hashFiles('**/apt-get-requirement.txt') }}

# Install the apt-get packages
- name: Install apt-get packages
run: cat apt-get-requirement.txt | xargs sudo apt-get -yq --no-install-recommends install

- name: Build
run: python setup.py build

- name: Pip install
run: |
python -m pip install --upgrade pip
rm -rf build
pip install .
- name: Test
run: |
pip install -r tests/requirements.txt
python tests/test_python.py
4 changes: 3 additions & 1 deletion input.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include "record.h"
#include "digger.h"
#include "game.h"
#ifdef _SDL
#ifdef _PYTHON
#include "python/python_kbd.h"
#elif defined(_SDL)
#include "sdl_kbd.h"
#elif defined(_VGL)
#include "fbsd_kbd.h"
Expand Down
5 changes: 5 additions & 0 deletions python/Symbol.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DIGGER_2ba68bed631b {
global: maininit; initgame; startlevel; gamestep; digger_controls; dgstate; getscreen; gettscore;
soundint; soundflag; musicflag;
local: *;
};
95 changes: 95 additions & 0 deletions python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Copyright (c) 2024 Sippy Software, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from ctypes import cdll, c_bool, c_ubyte, c_int, POINTER, Structure, c_int32
import os, site, sysconfig

from .env import DIGGER_MOD_NAME

_esuf = sysconfig.get_config_var('EXT_SUFFIX')
if not _esuf:
_esuf = '.so'
try:
import pathlib
_ROOT = str(pathlib.Path(__file__).parent.absolute())
except ImportError:
_ROOT = os.path.abspath(os.path.dirname(__file__))
#print('ROOT: ' + str(_ROOT))
modloc = site.getsitepackages()
modloc.insert(0, os.path.join(_ROOT, ".."))
for p in modloc:
try:
#print("Trying %s" % os.path.join(p, DIGGER_MOD_NAME + _esuf))
_digger = cdll.LoadLibrary(os.path.join(p, DIGGER_MOD_NAME + _esuf))
except:
continue
break
#else:
# raise ImportError("Cannot find %s" % DIGGER_MOD_NAME + _esuf)

class DiggerControls(Structure):
_fields_ = [
("leftpressed", c_bool),
("rightpressed", c_bool),
("uppressed", c_bool),
("downpressed", c_bool),
("f1pressed", c_bool),
("left2pressed", c_bool),
("right2pressed", c_bool),
("up2pressed", c_bool),
("down2pressed", c_bool),
("f12pressed", c_bool)
]

class Digger:
def __init__(self):
self.gamestep = _digger.gamestep
self.gamestep.restype = c_bool
self.maininit = _digger.maininit
self.maininit.restype = None
self.initgame = _digger.initgame
self.startlevel = _digger.startlevel
self.startlevel.restype = None
self.getscreen = _digger.getscreen
self.getscreen.argtypes = [POINTER(c_ubyte), c_int]
self.getscreen.restype = None
self.getscore = _digger.gettscore
self.getscore.argtypes = [c_int]
self.getscore.restype = c_int32
self.digger_controls = DiggerControls.in_dll(_digger, "digger_controls")
self.soundflag = c_bool.in_dll(_digger, 'soundflag')
self.musicflag = c_bool.in_dll(_digger, 'musicflag')

def game(self, steps=None):
self.maininit()
self.initgame()
self.startlevel()
while (steps is None or steps > 0) and self.gamestep(): steps -= 1
return steps

def screenshot(self):
buffer_size = 640 * 400
buffer = (c_ubyte * buffer_size)()
self.getscreen(buffer, buffer_size)
return buffer

1 change: 1 addition & 0 deletions python/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DIGGER_MOD_NAME='_digger'
26 changes: 26 additions & 0 deletions python/python_kbd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <stdbool.h>
#include <stdint.h>

#include "input.h"
#include "python_kbd.h"

struct digger_controls digger_controls = {0};
int keycodes[NKEYS][5] = {0};

void initkeyb(void)
{
digger_controls = (struct digger_controls){0};
}

int16_t getkey(bool scancode)
{
return -1;
}

void restorekeyb(void) {}
bool kbhit(void)
{
static bool state;
state = !state;
return state;
}
27 changes: 27 additions & 0 deletions python/python_kbd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

struct digger_controls {
bool leftpressed;
bool rightpressed;
bool uppressed;
bool downpressed;
bool f1pressed;
bool left2pressed;
bool right2pressed;
bool up2pressed;
bool down2pressed;
bool f12pressed;
};

extern struct digger_controls digger_controls;

#define leftpressed digger_controls.leftpressed
#define rightpressed digger_controls.rightpressed
#define uppressed digger_controls.uppressed
#define downpressed digger_controls.downpressed
#define f1pressed digger_controls.f1pressed
#define left2pressed digger_controls.left2pressed
#define right2pressed digger_controls.right2pressed
#define up2pressed digger_controls.up2pressed
#define down2pressed digger_controls.down2pressed
#define f12pressed digger_controls.f12pressed
22 changes: 22 additions & 0 deletions python/python_sound.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <stdint.h>
#include <stdbool.h>

#include "newsnd.h"

bool wave_device_available = false;

void pausesounddevice(bool pause) {}

void soundinitglob(uint16_t bufsize, uint16_t samprate) {}

void s1setupsound(void) {}

void s1killsound(void) {}

void s1timer2(uint16_t t2, bool mode) {}

void s1soundoff(void) {}

void s1setspkrt2(void) {}

void s1timer0(uint16_t t0) {}
84 changes: 84 additions & 0 deletions python/python_timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "def.h"
#include "digger_math.h"
#include "sprite.h"
#include "game.h"

struct timer_stats {
uint64_t inittimer;
uint64_t gethrt;
uint64_t getkips;
uint64_t s0soundoff;
uint64_t s0setspkrt2;
uint64_t s0settimer0;
uint64_t s0settimer2;
uint64_t s0timer0;
uint64_t s0timer2;
uint64_t s0soundkillglob;
} timer_stats = {0};

#define TIMERKNOB(n, r, ...) n(__VA_ARGS__) \
{ \
timer_stats.n += 1; \
r; \
}

void TIMERKNOB(inittimer, return, void)
int32_t TIMERKNOB(getkips, return 0, void)
void TIMERKNOB(s0soundoff, return, void)
void TIMERKNOB(s0setspkrt2, return, void)
void TIMERKNOB(s0settimer0, return, int16_t t0v)
void TIMERKNOB(s0settimer2, return, int16_t t0v)
void TIMERKNOB(s0timer0, return, int16_t t0v)
void TIMERKNOB(s0timer2, return, uint16_t t2v, bool mode)
void TIMERKNOB(s0soundkillglob, return, void)
//void inittimer(void) {}

void gethrt(bool)
{
timer_stats.gethrt += 1;
doscreenupdate();
}

#if 0
int32_t getkips(void)
{
FIXME("getkips called");
return(0);
}

void s0soundoff(void)
{
FIXME("s0soundoff called");
}

void s0setspkrt2(void)
{
FIXME("s0setspkrt2 called");
}

void s0settimer0(int16_t t0v)
{
FIXME("s0settimer0 called");
}

void s0settimer2(int16_t t0v)
{
FIXME("s0settimer2 called");
}

void s0timer0(int16_t t0v)
{
FIXME("s0timer0 called");
}

void s0timer2(uint16_t t2v, bool mode)
{
FIXME("s0timer2 called");
}

void s0soundkillglob(void)
{
/* No-op */
}
#endif

Loading

0 comments on commit 15ad649

Please sign in to comment.