Skip to content

Commit

Permalink
agt/panda game added.
Browse files Browse the repository at this point in the history
  • Loading branch information
schwarzlichtbezirk committed Dec 11, 2024
1 parent e4d3004 commit 7b855a7
Show file tree
Hide file tree
Showing 12 changed files with 458 additions and 58 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ Slots games server. Releases functionality for Megajack, Novomatic, NetEnt, BetS
Server provides HTTP-based API for popular slots and have well-optimized performance for thousands requests per second. Can be deployed on dedicated server or as portable application for Linux or Windows.

```text
total: 128 games, 65 algorithms, 9 providers
AGT: 46 games
total: 129 games, 66 algorithms, 9 providers
AGT: 47 games
Aristocrat: 4 games
BetSoft: 3 games
Megajack: 3 games
Expand All @@ -30,6 +30,7 @@ Slotopol: 4 games

*Last added games*:

* '[Panda](https://demo.agtsoftware.com/games/agt/panda)' AGT 3x3 videoslot
* '[Extra Spin](https://demo.agtsoftware.com/games/agt/extraspin)' AGT 5x3 videoslot
* '[Book of Set](https://demo.agtsoftware.com/games/agt/bookofset)' AGT 5x3 videoslot
* '[Pharaoh II](https://demo.agtsoftware.com/games/agt/pharaoh2)' AGT 5x3 videoslot
Expand Down
1 change: 1 addition & 0 deletions cmd/links.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import (
_ "github.com/slotopol/server/game/slot/agt/icequeen"
_ "github.com/slotopol/server/game/slot/agt/infinitygems"
_ "github.com/slotopol/server/game/slot/agt/luckyslot"
_ "github.com/slotopol/server/game/slot/agt/panda"
_ "github.com/slotopol/server/game/slot/agt/sevenhot"
_ "github.com/slotopol/server/game/slot/agt/shiningstars"
_ "github.com/slotopol/server/game/slot/agt/shiningstars100"
Expand Down
5 changes: 3 additions & 2 deletions docs/list-all.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
'Lucky Lady's Charm' Novomatic 5x3 videoslot
'Lucky Slot' AGT 5x3 videoslot
'Marco Polo' Novomatic 5x3 videoslot
'Panda' AGT 3x3 videoslot
'Pandora's Box' NetEnt 5x3 videoslot
'Panther Moon' Playtech 5x3 videoslot
'Pharaoh II' AGT 5x3 videoslot
Expand Down Expand Up @@ -131,8 +132,8 @@
'Wild Witches' NetEnt 5x3 videoslot
'Wizard' AGT 5x4 videoslot
total: 128 games, 65 algorithms, 9 providers
AGT: 46 games
total: 129 games, 66 algorithms, 9 providers
AGT: 47 games
Aristocrat: 4 games
BetSoft: 3 games
Megajack: 3 games
Expand Down
36 changes: 36 additions & 0 deletions game/slot/agt/panda/panda_calc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package panda

import (
"context"
"fmt"
"time"

"github.com/slotopol/server/game/slot"
)

func CalcStat(ctx context.Context, mrtp float64) float64 {
var reels, _ = slot.FindReels(ReelsMap, mrtp)
var g = NewGame()
var sln float64 = 1
g.Sel = int(sln)
var s slot.Stat

var dur = slot.ScanReels3x(ctx, &s, g, reels,
time.Tick(2*time.Second), time.Tick(2*time.Second))

var reshuf = float64(s.Reshuffles)
var lrtp, srtp = s.LinePay / reshuf / sln * 100, s.ScatPay / reshuf / sln * 100
var rtpsym = lrtp + srtp
var q = float64(s.FreeCount) / reshuf
var sq = 1 / (1 - q)
var rtpfs = sq * rtpsym
var rtp = rtpsym + q*rtpfs
fmt.Printf("completed %.5g%%, selected %d lines, time spent %v\n", reshuf/float64(s.Planned())*100, g.Sel, dur)
fmt.Printf("reels lengths [%d, %d, %d], total reshuffles %d\n",
len(reels.Reel(1)), len(reels.Reel(2)), len(reels.Reel(3)), reels.Reshuffles())
fmt.Printf("symbols: %.5g(lined) + %.5g(scatter) = %.6f%%\n", lrtp, srtp, rtpsym)
fmt.Printf("free spins %d, q = %.5g, sq = 1/(1-q) = %.6f\n", s.FreeCount, q, sq)
fmt.Printf("free games frequency: 1/%.5g\n", reshuf/float64(s.FreeHits))
fmt.Printf("RTP = %.5g(sym) + %.5g*%.5g(fg) = %.6f%%\n", rtpsym, q, rtpfs, rtp)
return rtp
}
26 changes: 26 additions & 0 deletions game/slot/agt/panda/panda_link.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//go:build !prod || full || agt

package panda

import (
"github.com/slotopol/server/game"
)

var Info = game.GameInfo{
Aliases: []game.GameAlias{
{Prov: "AGT", Name: "Panda"},
},
GP: game.GPretrig |
game.GPscat |
game.GPwild,
SX: 3,
SY: 3,
SN: len(LinePay),
LN: len(BetLines),
BN: 0,
RTP: game.MakeRtpList(ReelsMap),
}

func init() {
Info.SetupFactory(func() any { return NewGame() }, CalcStat)
}
249 changes: 249 additions & 0 deletions game/slot/agt/panda/panda_reel.go

Large diffs are not rendered by default.

104 changes: 104 additions & 0 deletions game/slot/agt/panda/panda_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package panda

// See: https://demo.agtsoftware.com/games/agt/panda

import (
"github.com/slotopol/server/game/slot"
)

// Lined payment.
var LinePay = [9][3]float64{
{0, 0, 500}, // 1 wild
{0, 0, 160}, // 2 bonsai
{0, 0, 80}, // 3 fish
{0, 0, 40}, // 4 fan
{0, 0, 20}, // 5 lamp
{0, 0, 20}, // 6 pot
{0, 0, 20}, // 7 flower
{0, 0, 10}, // 8 button
{}, // 9 scatter
}

// Bet lines
var BetLines = slot.BetLinesAgt3x3[:27]

type Game struct {
slot.Slot3x3 `yaml:",inline"`
}

// Declare conformity with SlotGame interface.
var _ slot.SlotGame = (*Game)(nil)

func NewGame() *Game {
return &Game{
Slot3x3: slot.Slot3x3{
Sel: len(BetLines),
Bet: 1,
},
}
}

const wild, scat = 1, 9

func (g *Game) Scanner(screen slot.Screen, wins *slot.Wins) {
for li := 1; li <= g.Sel; li++ {
var line = BetLines[li-1]

var numw, numl slot.Pos = 0, 3
var syml slot.Sym
var x slot.Pos
for x = 1; x <= 3; x++ {
var sx = screen.Pos(x, line)
if sx == wild {
if syml == 0 {
numw = x
}
} else if syml == 0 && sx != scat {
syml = sx
} else if sx != syml {
numl = x - 1
break
}
}

if numw == 3 {
var pay = LinePay[wild-1][numw-1]
*wins = append(*wins, slot.WinItem{
Pay: g.Bet * pay,
Mult: 1,
Sym: wild,
Num: numw,
Line: li,
XY: line.CopyL(numw),
})
} else if numl == 3 {
var pay = LinePay[syml-1][numl-1]
*wins = append(*wins, slot.WinItem{
Pay: g.Bet * pay,
Mult: 1,
Sym: syml,
Num: numl,
Line: li,
XY: line.CopyL(numl),
})
}
}

if count := screen.ScatNum(scat); count > 0 {
*wins = append(*wins, slot.WinItem{
Sym: scat,
Num: count,
XY: screen.ScatPos(scat),
Free: int(count),
})
}
}

func (g *Game) Spin(screen slot.Screen, mrtp float64) {
var reels, _ = slot.FindReels(ReelsMap, mrtp)
screen.Spin(reels)
}

func (g *Game) SetSel(sel int) error {
return slot.ErrNoFeature
}
4 changes: 2 additions & 2 deletions game/slot/agt/shiningstars/shiningstars_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ func (g *Game) ScanScatters(screen slot.Screen, wins *slot.Wins) {
Num: count,
XY: screen.ScatPos(scat1),
})
} else if count := screen.ScatNumOdd(scat2); count >= 3 {
} else if count := screen.ScatNum(scat2); count >= 3 {
var pay = ScatPay2[count-1]
*wins = append(*wins, slot.WinItem{
Pay: g.Bet * float64(g.Sel) * pay,
Mult: 1,
Sym: scat2,
Num: count,
XY: screen.ScatPosOdd(scat2),
XY: screen.ScatPos(scat2),
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions game/slot/agt/shiningstars100/shiningstars100_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ func (g *Game) ScanScatters(screen *slot.Screen5x4, wins *slot.Wins) {
Num: count,
XY: screen.ScatPos(scat1),
})
} else if count := screen.ScatNumOdd(scat2); count >= 3 {
} else if count := screen.ScatNum(scat2); count >= 3 {
var pay = ScatPay2[count-1]
*wins = append(*wins, slot.WinItem{
Pay: g.Bet * float64(g.Sel) * pay,
Mult: 1,
Sym: scat2,
Num: count,
XY: screen.ScatPosOdd(scat2),
XY: screen.ScatPos(scat2),
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions game/slot/novomatic/columbus/columbus_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@ func (g *Game) ScanLined(screen slot.Screen, wins *slot.Wins) {

// Scatters calculation.
func (g *Game) ScanScatters(screen slot.Screen, wins *slot.Wins) {
if count := screen.ScatNumOdd(scat); count >= 3 {
if count := screen.ScatNum(scat); count >= 3 {
*wins = append(*wins, slot.WinItem{
Mult: 1,
Sym: scat,
Num: count,
XY: screen.ScatPosOdd(scat),
XY: screen.ScatPos(scat),
Free: 10,
})
}
Expand Down
48 changes: 0 additions & 48 deletions game/slot/screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ type Screen interface {
Spin(reels Reels) // fill the screen with random hits on those reels
SymNum(sym Sym) (n Pos) // returns number of symbols on the screen that can repeats on reel
ScatNum(scat Sym) (n Pos) // returns number of scatters on the screen
ScatNumOdd(scat Sym) (n Pos) // returns number of scatters on the screen on odd reels
ScatNumCont(scat Sym) (n Pos) // returns number of continuous scatters on the screen
ScatPos(scat Sym) Linex // returns line with scatters positions on the screen
ScatPosOdd(scat Sym) Linex // returns line with scatters positions on the screen on odd reels
ScatPosCont(scat Sym) Linex // returns line with continuous scatters positions on the screen
FillSym() Sym // returns symbol that filled whole screen, or 0
Free() // put object to pool
Expand Down Expand Up @@ -127,21 +125,6 @@ func (s *Screenx) ScatNum(scat Sym) (n Pos) {
return
}

func (s *Screenx) ScatNumOdd(scat Sym) (n Pos) {
var x, y, i Pos
loopx:
for x = 0; x < s.sx; x += 2 {
i = x * s.sy
for y = range s.sy {
if s.data[i+y] == scat {
n++
continue loopx
}
}
}
return
}

func (s *Screenx) ScatNumCont(scat Sym) (n Pos) {
var x, y, i Pos
loopx:
Expand Down Expand Up @@ -293,17 +276,6 @@ func (s *Screen3x3) ScatNum(scat Sym) (n Pos) {
return
}

func (s *Screen3x3) ScatNumOdd(scat Sym) (n Pos) {
var x Pos
for x = 0; x < 3; x += 2 {
var r = s[x]
if r[0] == scat || r[1] == scat || r[2] == scat {
n++
}
}
return
}

func (s *Screen3x3) ScatNumCont(scat Sym) (n Pos) {
var x Pos
for x = 0; x < 3; x++ {
Expand Down Expand Up @@ -444,16 +416,6 @@ func (s *Screen5x3) ScatNum(scat Sym) (n Pos) {
return
}

func (s *Screen5x3) ScatNumOdd(scat Sym) (n Pos) {
for x := 0; x < 5; x += 2 {
var r = s[x]
if r[0] == scat || r[1] == scat || r[2] == scat {
n++
}
}
return
}

func (s *Screen5x3) ScatNumCont(scat Sym) (n Pos) {
for x := 0; x < 5; x++ {
var r = s[x]
Expand Down Expand Up @@ -593,16 +555,6 @@ func (s *Screen5x4) ScatNum(scat Sym) (n Pos) {
return
}

func (s *Screen5x4) ScatNumOdd(scat Sym) (n Pos) {
for x := 0; x < 5; x += 2 {
var r = s[x]
if r[0] == scat || r[1] == scat || r[2] == scat || r[3] == scat {
n++
}
}
return
}

func (s *Screen5x4) ScatNumCont(scat Sym) (n Pos) {
for x := 0; x < 5; x++ {
var r = s[x]
Expand Down
30 changes: 30 additions & 0 deletions helper/panda.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
local path = arg[0]:match("(.*[/\\])")
dofile(path.."lib/reelgen.lua")

local symset = {
1, -- 1 wild
3, -- 2 bonsai
5, -- 3 fish
5, -- 4 fan
9, -- 5 lamp
10, -- 6 pot
10, -- 7 flower
13, -- 8 button
1, -- 9 scatter
}

local chunklen = {
1, -- 1 wild
3, -- 2 bonsai
3, -- 3 fish
3, -- 4 fan
5, -- 5 lamp
5, -- 6 pot
5, -- 7 flower
5, -- 8 button
1, -- 9 scatter
}

math.randomseed(os.time())
local reel, iter = makereelhot(symset, 3, {}, chunklen, true)
printreel(reel, iter)

0 comments on commit 7b855a7

Please sign in to comment.